【传送门:BZOJ1103】
简要题意:
给出一棵树,树上的根节点为1,一开始所有的边的边权都为1,给出两种操作:
1.M x求出x点到根节点的边权和
2.A x y表示x到y的这条边的边权变为0
题解:
树链剖分裸题
把题意简要提取之后就变成裸题了。。
没什么好讲
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct node { int x,y,next; }a[510000];int len,last[310000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } struct trnode { int l,r,lc,rc,c; }tr[510000];int trlen; void bt(int l,int r) { trlen++;int now=trlen; tr[now].l=l;tr[now].r=r;tr[now].c=0; tr[now].lc=tr[now].rc=-1; if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); } } int fa[310000],dep[310000],tot[310000],son[310000]; void pre_tree_node(int x) { son[x]=0;tot[x]=1; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa[x]) { fa[y]=x; dep[y]=dep[x]+1; pre_tree_node(y); if(tot[y]>tot[son[x]]) son[x]=y; tot[x]+=tot[y]; } } } int z,ys[310000],top[310000]; void pre_tree_edge(int x,int tp) { ys[x]=++z;top[x]=tp; if(son[x]!=0) pre_tree_edge(son[x],tp); for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=fa[x]&&y!=son[x]) pre_tree_edge(y,y); } } void change(int now,int x,int c) { if(tr[now].l==tr[now].r) { tr[now].c=c; return ; } int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(x<=mid) change(lc,x,c); else change(rc,x,c); tr[now].c=tr[lc].c+tr[rc].c; } int getsum(int now,int l,int r) { if(tr[now].l==l&&tr[now].r==r) return tr[now].c; int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(r<=mid) return getsum(lc,l,r); else if(l>mid) return getsum(rc,l,r); else return getsum(lc,l,mid)+getsum(rc,mid+1,r); } int solve(int x,int y) { int tx=top[x],ty=top[y],ans=0; while(tx!=ty) { if(dep[tx]>dep[ty]) { swap(tx,ty); swap(x,y); } ans+=getsum(1,ys[ty],ys[y]); y=fa[ty];ty=top[y]; } if(x==y) return ans; else { if(dep[x]>dep[y]) swap(x,y); return ans+getsum(1,ys[son[x]],ys[y]); } } struct enode { int x,y; }e[310000]; int main() { int n; scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%d%d",&e[i].x,&e[i].y); ins(e[i].x,e[i].y);ins(e[i].y,e[i].x); } dep[1]=0;fa[1]=0;pre_tree_node(1); z=0;pre_tree_edge(1,1); trlen=0;bt(1,z); int m;scanf("%d",&m); for(int i=1;i<n;i++) { if(dep[e[i].x]>dep[e[i].y]) swap(e[i].x,e[i].y); change(1,ys[e[i].y],1); } char st[3]; for(int i=1;i<=n+m-1;i++) { scanf("%s",st+1); if(st[1]=='A') { int x,y; scanf("%d%d",&x,&y); if(dep[x]>dep[y]) swap(x,y); change(1,ys[y],0); } else { int x; scanf("%d",&x); printf("%d ",solve(1,x)); } } return 0; }