题目描述:
给定一颗树,求某个节点的子树的val值之和
可以用树的前序遍历给每一个节点编号,从而可以确定一个节点的子树的范围,这样就可以进行直接在区间上进行统计了。
vector < int > Map[maxN]写成typedef vector <int> INT; vector <INT> Map(maxN);就不超时了。
线段树
#include <cstdio> #include <cstring> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #define LL long long using namespace std; //线段树 //区间每点增值,求区间和 const int maxN = 110000; struct node { int lt, rt; int val; }tree[4*maxN]; //向上更新 void pushUp(int id) { tree[id].val = tree[id<<1].val + tree[id<<1|1].val; } //建立线段树 void build(int lt, int rt, int id) { tree[id].lt = lt; tree[id].rt = rt; // tree[id].val = 1;//每段的初值,根据题目要求 if (lt == rt) { tree[id].val=1; return; } int mid = (lt+rt)>>1; build(lt, mid, id<<1); build(mid+1, rt, id<<1|1); pushUp(id); } //增加区间内每个点固定的值 void add(int lt, int rt, int id) { if (lt <= tree[id].lt && rt >= tree[id].rt) { if(tree[id].val==1) tree[id].val=0; else tree[id].val=1; return; } int mid = (tree[id].lt+tree[id].rt)>>1; if (lt <= mid) add(lt, rt, id<<1); if (rt > mid) add(lt, rt, id<<1|1); pushUp(id); } //查询某段区间内的和 int query(int lt, int rt, int id) { if (lt <= tree[id].lt && rt >= tree[id].rt) return tree[id].val; int mid = (tree[id].lt+tree[id].rt)>>1; int ans = 0; if (lt <= mid) ans += query(lt, rt, id<<1); if (rt > mid) ans += query(lt, rt, id<<1|1); return ans; } struct NODE { int cnt,l,r; }a[maxN]; typedef vector<int > INT; vector<INT > Map(maxN); int vis[maxN]; int number; void dfs(int fa) { for(int i=0;i<Map[fa].size();i++) { int son=Map[fa][i]; if(vis[son]==0) { a[son].cnt=++number; a[son].l= number; vis[son]=1; dfs(son); a[son].r=number; } } } void init() { for(int i=0;i<maxN;i++) Map[i].clear(); } int main() { // freopen("test.txt","r",stdin); int n,m; while(~scanf("%d",&n)) { init(); for(int i=1;i<=n-1;i++) { int from,to; scanf("%d%d",&from,&to); Map[from].push_back(to); Map[to].push_back(from); } number=1; memset(vis,0,sizeof(vis)); a[1].cnt=1; a[1].l=1; vis[1]=1; dfs(1); a[1].r=number; build(a[1].l,a[1].r,1); //for(int i=1;i<=9;i++) // printf("%d %d %d ",a[i].cnt,a[i].l,a[i].r); int M; scanf("%d",&M); char str[5]; int id; while(M--) { scanf("%s%d",str,&id); //printf("%s ",str); if(str[0]=='Q') { printf("%d ",query(a[id].l,a[id].r,1) ); } if(str[0]=='C') { add(a[id].cnt,a[id].cnt,1); } } } return 0; }
树状数组
#include <cstdio> #include <cstring> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <vector> #define LL long long using namespace std; const int maxN = 110000; int n; //树状数组 int C[maxN],A[maxN]; int lowbit(int x) { return x&(-x); } int sum(int x) { int ret=0; while(x>0) { ret+=C[x]; x-=lowbit(x); } return ret; } void update(int x,int pls) { int d; if(pls==0) { if(A[x]==0) d=1; if(A[x]==1) d=-1; } else d=1; A[x]+=d; while(x<=n) { C[x]+=d; x+=lowbit(x); } } struct NODE { int cnt,l,r; }a[maxN]; typedef vector<int> INT; vector < INT > Map(maxN); int vis[maxN]; int number; void dfs(int fa) { for(int i=0;i<Map[fa].size();i++) { int son=Map[fa][i]; if(vis[son]==0) { a[son].cnt=++number; a[son].l= number; vis[son]=1; dfs(son); a[son].r=number; } } } void init() { for(int i=0;i<maxN;i++) Map[i].clear(); } int main() { //freopen("test.txt","r",stdin); while(~scanf("%d",&n)) { init(); for(int i=1;i<=n-1;i++) { int from,to; scanf("%d%d",&from,&to); Map[from].push_back(to); Map[to].push_back(from); } number=1; memset(vis,0,sizeof(vis)); a[1].cnt=1; a[1].l=1; vis[1]=1; dfs(1); a[1].r=number; memset(C,0,sizeof(C)); memset(A,0,sizeof(A)); for(int i=1;i<=n;i++) update(i,1); int M; scanf("%d",&M); char str[5]; int id; while(M--) { scanf("%s%d",str,&id); if(str[0]=='Q') { printf("%d ",sum(a[id].r) -sum(a[id].l-1) ); } if(str[0]=='C') { update(a[id].cnt,0); } } } return 0; }