I. A Simple Tree Problem
Time Limit: 3000ms
Memory Limit: 65536KB
64-bit integer IO format: %lld Java class name: MainGiven a rooted tree, each node has a boolean (0 or 1) labeled on it. Initially, all the labels are 0.
We define this kind of operation: given a subtree, negate all its labels.
And we want to query the numbers of 1's of a subtree.
Input
Multiple test cases.
First line, two integer N and M, denoting the numbers of nodes and numbers of operations and queries.(1<=N<=100000, 1<=M<=10000)
Then a line with N-1 integers, denoting the parent of node 2..N. Root is node 1.
Then M lines, each line are in the format "o node" or "q node", denoting we want to operate or query on the subtree with root of a certain node.
Output
For each query, output an integer in a line.
Output a blank line after each test case.
Sample Input
3 2 1 1 o 2 q 1
Sample Output
1
解题:利用dfs记录时间戳,也就是记录区间长度,恰好的包含关系,为建立线段树带来很大的方便,不需要建立N棵线段树,但以某一点为根节点的字孩子区间一定是父节点的区间的子区间。这样好的性质,恰好可以映射到线段树上。。。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <vector> 6 #include <climits> 7 #include <algorithm> 8 #include <cmath> 9 #define LL long long 10 #define INF 0x3f3f3f 11 using namespace std; 12 const int maxn = 100010; 13 int n,m,id; 14 vector<int>g[maxn]; 15 int len[maxn<<2],cnt[maxn<<2],mark[maxn<<2]; 16 struct node{ 17 int lt,rt; 18 }tree[maxn<<2]; 19 void dfs(int u){ 20 tree[u].lt = ++id; 21 for(int i = 0; i < g[u].size(); i++){ 22 dfs(g[u][i]); 23 } 24 tree[u].rt = id; 25 } 26 void build(int lt,int rt,int v){ 27 cnt[v] = mark[v] = 0; 28 len[v] = rt-lt+1; 29 if(lt == rt) return; 30 int mid = (lt+rt)>>1; 31 build(lt,mid,v<<1); 32 build(mid+1,rt,v<<1|1); 33 } 34 void push_down(int v){ 35 if(mark[v]){ 36 cnt[v<<1] = len[v<<1]-cnt[v<<1]; 37 mark[v<<1] ^= 1; 38 cnt[v<<1|1] = len[v<<1|1]-cnt[v<<1|1]; 39 mark[v<<1|1] ^= 1; 40 mark[v] = 0; 41 } 42 } 43 void update(int x,int y,int lt,int rt,int v){ 44 if(lt >= x && rt <= y){ 45 cnt[v] = len[v] - cnt[v]; 46 if(lt == rt) return; 47 mark[v] ^= 1; 48 return; 49 } 50 push_down(v); 51 int mid = (lt+rt)>>1; 52 if(x <= mid) update(x,y,lt,mid,v<<1); 53 if(y > mid) update(x,y,mid+1,rt,v<<1|1); 54 cnt[v] = cnt[v<<1]+cnt[v<<1|1]; 55 } 56 int query(int x,int y,int lt,int rt,int v){ 57 int ans = 0; 58 if(x <= lt && rt <= y){ 59 return cnt[v]; 60 } 61 push_down(v); 62 int mid = (lt+rt)>>1; 63 if(x <= mid) ans += query(x,y,lt,mid,v<<1); 64 if(y > mid) ans += query(x,y,mid+1,rt,v<<1|1); 65 return ans; 66 } 67 int main(){ 68 int i,temp; 69 char s; 70 while(~scanf("%d%d",&n,&m)){ 71 for(i = 0; i <= n; i++) 72 g[i].clear(); 73 for(i = 2; i <= n; i++){ 74 scanf("%d",&temp); 75 g[temp].push_back(i); 76 } 77 id = 0; 78 dfs(1); 79 build(1,n,1); 80 while(m--){ 81 cin>>s>>temp; 82 if(s == 'o'){ 83 update(tree[temp].lt,tree[temp].rt,1,n,1); 84 }else cout<<query(tree[temp].lt,tree[temp].rt,1,n,1)<<endl; 85 } 86 cout<<endl; 87 } 88 return 0; 89 }