HDU 3974 Assign the task
阿新 • • 發佈:2017-08-06
開始時間 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] 31void 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