CodeForces 343D Water Tree(dfs序 線段樹)
阿新 • • 發佈:2019-02-01
題意:給你一顆n個節點的樹,1為根,初始時所有節點都為0,有三種操作:
1 x :將x及其子樹的所有節點都變為1
2 x :將x及其祖先都變為0
3 x :查詢x的值
思路:可以先求出dfs序,對於操作1,我們可以用線段樹區間更新in[x]至out[x];對於操作2,需要更新它及其祖先,
不太好操作,我們可以只將x變為0,這樣對於操作3,我們可以查詢其子樹最小值,如果是0就代表它也會變為0,否
則就是1。這樣一來操作1可能會把操作2的0給覆蓋掉,所以在進行操作1時要把其父節點變為0。
程式碼:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5e5+5; int tree[maxn*4], lazy[maxn*4], in[maxn*4], out[maxn*4], fa[maxn*4], tot; vector<int> g[maxn]; void dfs(int u, int pre) { in[u] = ++tot; fa[u] = pre; for(int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if(v != pre) dfs(v, u); } out[u] = tot; } void push_up(int root) { tree[root] = min(tree[root*2], tree[root*2+1]); } void push_down(int root) { if(lazy[root] != -1) { tree[root*2] = tree[root*2+1] = lazy[root]; lazy[root*2] = lazy[root*2+1] = lazy[root]; lazy[root] = -1; } } void update(int root, int l, int r, int i, int j, int op) { if(i <= l && j >= r) { tree[root] = lazy[root] = op; return ; } push_down(root); int mid = (l+r)/2; if(i <= mid) update(root*2, l, mid, i, j, op); if(j > mid) update(root*2+1, mid+1, r, i, j, op); push_up(root); } int query(int root, int l, int r, int i, int j) { if(i <= l && j >= r) return tree[root]; push_down(root); int mid = (l+r)/2; if(j <= mid) return query(root*2, l, mid, i, j); else if(i > mid) return query(root*2+1, mid+1, r, i, j); else return min(query(root*2, l, mid, i, j), query(root*2+1, mid+1, r, i, j)); } int main(void) { int n; while(cin >> n) { tot = 0; memset(tree, 0, sizeof(tree)); memset(lazy, -1, sizeof(lazy)); for(int i = 0; i <= n; i++) g[i].clear(); for(int i = 0; i < n-1; i++) { int u, v; scanf("%d%d", &u, &v); g[u].push_back(v); g[v].push_back(u); } dfs(1, 0); int q; scanf("%d", &q); while(q--) { int cmd, x; scanf("%d%d", &cmd, &x); if(cmd == 1) { int tmp = query(1, 1, tot, in[x], out[x]); update(1, 1, tot, in[x], out[x], 1); if(!tmp && fa[x]) update(1, 1, tot, in[fa[x]], in[fa[x]], 0); } else if(cmd == 2) update(1, 1, tot, in[x], in[x], 0); else printf("%d\n", query(1, 1, tot, in[x], out[x])); } } return 0; }