给一个节点数为n的树,m个操作,每个操作包涵两个数a,b,第i次操作时,向节点a及其子树,节点b及其子树的数据序列中添加i。m次操作完成后,对于每个节点,查询这棵树上有多少个节点与当前节点至少包涵一个相同数。
首先对子树操作的话,先对树做dfs并编号,这样某节点的子树节点的编号一定是一个连续的区间,并记录一下每个节点子树节点编号的范围,这样操作就是一个线段树的区间更新了。
对于操作,可以开个数组或者向量,que[i],保存下所有与i同时操作的节点,这样在查询节点i的时候,先执行que[i]所有的操作,求一下此时有多少个节点被覆盖就行了。查询的时候依然是按dfs序查询,并且一个节点查询结束后要恢复数据。
另外,还有一个坑,数据给的时候并没有保证边a,b一定是a指向b..只保证了1一定是根...所以还是要存成无向图,然后从1开始dfs...
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> #include <queue> #include <stack> #include <string> #include <cstring> #include <vector> #include <map> #define lson id<<1,l,m #define rson id<<1|1,m+1,r using namespace std; typedef long long ll; const int maxn=300000+100; int x,y; struct link_edge { int v,next; }edge[maxn]; int en; int g[maxn]; int ct[maxn]; struct node { int id,pre; int l,r; int data; }tree[maxn]; vector<int>que[maxn]; int n,m,p,q; int id; int ans[maxn]; struct segmenttree { int add[maxn<<2]; int dt[maxn<<2]; void init() { memset(dt,0,sizeof dt); memset(add,0,sizeof add); } void pushup(int id,int m) { if (add[id]) { dt[id]=m; return; } else if (m==1) dt[id]=0; else dt[id]=dt[id<<1]+dt[id<<1|1]; } void modify(int L,int R,int id,int l,int r,int c) { if (L==l && R==r) { add[id]+=c; pushup(id,r-l+1); return; } int m=(l+r)>>1; if (R<=m) modify(L,R,lson,c); else if (L>m) modify(L,R,rson,c); else { modify(L,m,lson,c); modify(m+1,R,rson,c); } pushup(id,r-l+1); } }sgt; void dfs(int i,int pre) { tree[i].id=id; for (int j=g[i]; j!=-1; j=edge[j].next) { if (edge[j].v==pre) continue; id++; dfs(edge[j].v,i); } } void dfs_find(int i,int &minn,int &maxx,int pre) { int k; minn=tree[i].id; maxx=tree[i].id; for (int j=g[i]; j!=-1; j=edge[j].next) { k=edge[j].v; if (k==pre) continue; dfs_find(k,tree[k].l,tree[k].r,i); // minn=min(minn,min(tree[k].l,tree[k].id)); maxx=max(maxx,tree[k].r); } if (minn==999999999) minn=tree[i].id; } void work(int u,int pre) { for (int i=0; i<que[u].size(); i++) { int v=que[u][i]; sgt.modify(tree[v].l,tree[v].r,1,1,n,1); } ans[u]+=sgt.dt[1]; if (ans[u]) ans[u]--; for (int j=g[u]; j!=-1; j=edge[j].next) { if (edge[j].v==pre) continue; work(edge[j].v,u); } for (int i=0; i<que[u].size(); i++) { int v=que[u][i]; sgt.modify(tree[v].l,tree[v].r,1,1,n,-1); } } int main() { // freopen("in.txt","r",stdin); memset(g,-1,sizeof g); memset(ans,0,sizeof ans); en=0; scanf("%d%d",&n,&m); for (int i=1; i<n; i++) { scanf("%d%d",&x,&y); edge[en].v=y; edge[en].next=g[x]; g[x]=en; en++; edge[en].v=x; edge[en].next=g[y]; g[y]=en; en++; } tree[1].id=1; id=1; dfs(1,-1); dfs_find(1,tree[1].l,tree[1].r,-1); // for (int i=1; i<=n; i++) // cout<<tree[i].id<<" "<<tree[i].l<<" "<<tree[i].r<<endl; sgt.init(); for (int i=1; i<=m; i++) { scanf("%d%d",&x,&y); que[x].push_back(x); que[x].push_back(y); que[y].push_back(x); que[y].push_back(y); } work(1,-1); for(int i=1; i<=n; i++) cout<<ans[i]<<" "; cout<<endl; return 0; }