1. 程式人生 > >HDU 3974 Assign the task

HDU 3974 Assign the task

開始時間 set sizeof 代碼 task spa 以及 show 靜態

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3974

解題思路:深搜設置時間戳,然後線段樹上更新查詢即可。

第一次寫,還算順利(盡管wa了兩發)。

代碼:

  1 const int maxn = 5e4 + 5;
  2 //靜態鏈表前向星保存圖
  3 struct Edge{
  4     int to, next;
  5     int val;
  6 };
  7 int head[maxn], tot;
  8 Edge edges[maxn];
  9 //dfs 時間戳 - st 表示開始時間, ed 表示結束時間, cnt 總的節點個數
10 int st[maxn], ed[maxn], cnt; 11 int tree[maxn * 4], ass[maxn * 4], vis[maxn];//tree 線段樹節點值, ass 區間更新延遲標記, vis 查找根節點用 12 int n, m; 13 14 void init(){ 15 memset(head, -1, sizeof(head)); 16 memset(tree, -1, sizeof(tree)); 17 memset(ass, -1, sizeof(ass)); 18 memset(vis, 0, sizeof
(vis)); 19 tot = 0; 20 cnt = 0; 21 } 22 void addEdge(int u, int v, int w){ 23 edges[tot].to = v; 24 edges[tot].val = w; 25 edges[tot].next = head[u]; 26 head[u] = tot++; 27 } 28 //深度優先搜索為每個節點設置時間戳 29 //畫個圖很容易看到對應區間關系,父節點區間總是包含子節點的區間 30 //在線段樹的節點中,葉子節點對應的標號是每個節點的起始時間st[u] 31
void dfs(int u){ 32 cnt++; 33 //起始時間 34 st[u] = cnt; 35 for(int i = head[u]; i != -1; i = edges[i].next){ 36 //對子節點深搜 37 dfs(edges[i].to); 38 } 39 //結束時間 40 ed[u] = cnt; 41 } 42 void build(int l, int r, int k){ 43 if(l == r) { 44 ass[k] = tree[k] = -1; 45 return; 46 } 47 int mid = (l + r) >> 1, lc = k << 1, rc = k << 1; 48 build(l, mid, lc); 49 build(mid + 1, r,rc); 50 } 51 //延遲標記ass,初始為-1,每次update或者query時要pushdown到子節點 52 void update(int ul, int ur, int x, int l, int r, int k){ 53 if(ul == l && ur == r){ 54 ass[k] = x; 55 return; 56 } 57 if(ul > r || ur < l) return; 58 if(l == r){ 59 tree[k] = x; 60 ass[k] = -1; 61 return; 62 } 63 64 int lc = k << 1, rc = k << 1 | 1; 65 if(ass[k] != -1){ 66 tree[k] = ass[k]; 67 ass[lc] = ass[k]; 68 ass[rc] = ass[k]; 69 ass[k] = -1; 70 } 71 72 int mid = (l + r) >> 1; 73 update(ul, ur, x, l, mid, lc); 74 update(ul, ur, x, mid + 1, r, rc); 75 } 76 77 int query(int qu, int l, int r, int k){ 78 if(l == qu && r == qu){ 79 if(ass[k] != -1){ 80 tree[k] = ass[k]; 81 return ass[k]; 82 } 83 return tree[k]; 84 } 85 int lc = k << 1, rc = k << 1 | 1; 86 if(ass[k] != -1){ 87 tree[k] = ass[k]; 88 ass[lc] = ass[k]; 89 ass[rc] = ass[k]; 90 ass[k] = -1; 91 } 92 93 94 int mid = (l + r) >> 1; 95 if(qu <= mid) return query(qu, l, mid, lc); 96 else return query(qu, mid + 1, r, rc); 97 } 98 99 int main(){ 100 int T; 101 scanf("%d", &T); 102 for(int t = 1; t <= T; t++){ 103 printf("Case #%d:\n", t); 104 init(); 105 scanf("%d", &n); 106 for(int i = 2; i <= n; i++){ 107 int u, v; 108 scanf("%d %d", &u, &v); 109 addEdge(v, u, 1); 110 vis[u]++; 111 } 112 for(int i = 1; i <= n; i++){ 113 //從原樹根深搜 114 if(vis[i] == 0){ 115 dfs(i); 116 break; 117 } 118 } 119 build(1, cnt, 1); 120 scanf("%d", &m); 121 while(m--){ 122 char ch; 123 scanf(" %c", &ch); 124 if(ch == C){ 125 int x; 126 scanf("%d", &x); 127 //st[x]為原樹x節點對應線段樹中的節點編號 128 printf("%d\n", query(st[x], 1, cnt, 1)); 129 } 130 else{ 131 int x, y; 132 scanf("%d %d", &x, &y); 133 //更新時[st[], ed[]]包含了原樹上x節點以及其所有子節點 134 update(st[x], ed[x], y, 1, cnt, 1); 135 } 136 } 137 } 138 }

題目:

const int maxn = 5e4 + 5;
//靜態鏈表前向星保存圖
struct Edge{
	int to, next;
	int val;
};
int head[maxn], tot;
Edge edges[maxn];
//dfs 時間戳 - st 表示開始時間, ed 表示結束時間, cnt 總的節點個數
int st[maxn], ed[maxn], cnt;
int tree[maxn * 4], ass[maxn * 4], vis[maxn];//tree 線段樹節點值, ass 區間更新延遲標記, vis 查找根節點用
int n, m;

void init(){
	memset(head, -1, sizeof(head));
	memset(tree, -1, sizeof(tree));
	memset(ass, -1, sizeof(ass));
	memset(vis, 0, sizeof(vis));
	tot = 0;
	cnt = 0;
}
void addEdge(int u, int v, int w){
	edges[tot].to = v;
	edges[tot].val = w;
	edges[tot].next = head[u];
	head[u] = tot++;
}
//深度優先搜索為每個節點設置時間戳
//畫個圖很容易看到對應區間關系,父節點區間總是包含子節點的區間
//在線段樹的節點中,葉子節點對應的標號是每個節點的起始時間st[u]
void dfs(int u){
	cnt++;
    //起始時間
	st[u] = cnt;
	for(int i = head[u]; i != -1; i = edges[i].next){
        //對子節點深搜
		dfs(edges[i].to);
	}
    //結束時間
	ed[u] = cnt;
}
void build(int l, int r, int k){
	if(l == r) {
		ass[k] = tree[k] = -1;
		return;
	}
	int mid = (l + r) >> 1, lc = k << 1, rc = k << 1;
	build(l, mid, lc);
	build(mid + 1, r,rc);
}
//延遲標記ass,初始為-1,每次update或者query時要pushdown到子節點
void update(int ul, int ur, int x, int l, int r, int k){
	if(ul == l && ur == r){
		ass[k] = x;
		return;
	}
	if(ul > r || ur < l) return;
	if(l == r){
		tree[k] = x;
		ass[k] = -1;
		return;
	}
	
	int lc = k << 1, rc = k << 1 | 1;
	if(ass[k] != -1){
		tree[k] = ass[k];
		ass[lc] = ass[k];
		ass[rc] = ass[k];
		ass[k] = -1;
	}
	
	int mid = (l + r) >> 1;
	update(ul, ur, x, l, mid, lc);
	update(ul, ur, x, mid + 1, r, rc);
}

int query(int qu, int l, int r, int k){
	if(l == qu && r == qu){
		if(ass[k] != -1){
			tree[k] = ass[k];
			return ass[k];
		}
		return tree[k];
	}
	int lc = k << 1, rc = k << 1 | 1;
	if(ass[k] != -1){
		tree[k] = ass[k];
		ass[lc] = ass[k];
		ass[rc] = ass[k];
		ass[k] = -1;
	}
	
	
	int mid = (l + r) >> 1;
	if(qu <= mid) return query(qu, l, mid, lc);
	else return query(qu, mid + 1, r, rc);
}

int main(){
	int T;
	scanf("%d", &T);
	for(int t = 1; t <= T; t++){
		printf("Case #%d:\n", t);
		init();
		scanf("%d", &n);
		for(int i = 2; i <= n; i++){
			int u, v;
			scanf("%d %d", &u, &v);
			addEdge(v, u, 1);
			vis[u]++;
		}
		for(int i = 1; i <= n; i++){
            //從原樹根深搜
			if(vis[i] == 0){
				dfs(i);
				break;
			}
		}
		build(1, cnt, 1);
		scanf("%d", &m);
		while(m--){
			char ch;
			scanf(" %c", &ch);
			if(ch == ‘C‘){
				int x;
				scanf("%d", &x);
                //st[x]為原樹x節點對應線段樹中的節點編號
				printf("%d\n", query(st[x], 1, cnt, 1));
			}
			else{
				int x, y;
				scanf("%d %d", &x, &y);
                //更新時[st[], ed[]]包含了原樹上x節點以及其所有子節點
				update(st[x], ed[x], y, 1, cnt, 1);
			}
		}
	}
}

HDU 3974 Assign the task