bzoj4448: [Scoi2015]情报传递
一眼上去,嗯,这题主席树,码量太大了周末再做。
今天,诶好像还要树剖?
对于每一条重链,用主席树维护,主席树建立权值线段树,求区间的值的个数。
发现是在线修改(冒汗我忘了主席树怎么这样搞)
然后Rose说离线就可以了。(机智)
然后飞快的码,调了调数据。结果第一次T掉了,要数据,调不出来,被肉丝和星感大神联合D飞,树剖模版打错了。。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct node { int x,y,next; }a[210000];int len,last[210000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int fa[210000],son[210000],tot[210000],dep[210000]; void pre_tree_node(int x) { tot[x]=1;son[x]=0; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; 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[210000],tp[210000]; void pre_tree_edge(int x,int t) { ys[x]=++z;tp[x]=t; if(son[x]!=0)pre_tree_edge(son[x],t); for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=son[x])pre_tree_edge(y,y); } } //----------composition-------------- struct chairmantree { int lc,rc,c; }tr[4100000];int trlen,rt[210000]; int maketree(int now,int l,int r,int p) { if(now==0)now=++trlen; tr[now].c++; if(l<r) { int mid=(l+r)/2; if(p<=mid)tr[now].lc=maketree(tr[now].lc,l,mid,p); else tr[now].rc=maketree(tr[now].rc,mid+1,r,p); } return now; } int merge(int x,int y) { if(x==0||y==0)return x+y; tr[x].c+=tr[y].c; tr[x].lc=merge(tr[x].lc,tr[y].lc); tr[x].rc=merge(tr[x].rc,tr[y].rc); return x; } int getsum(int x,int y,int l,int r,int ll,int rr) { if(x==0&&y==0)return 0; if(l==ll&&r==rr)return tr[y].c-tr[x].c; int mid=(l+r)/2; if(rr<=mid)return getsum(tr[x].lc,tr[y].lc,l,mid,ll,rr); else if(mid+1<=ll)return getsum(tr[x].rc,tr[y].rc,mid+1,r,ll,rr); else return getsum(tr[x].lc,tr[y].lc,l,mid,ll,mid)+getsum(tr[x].rc,tr[y].rc,mid+1,r,mid+1,rr); } //-------------chairmantree------------ int n; int solve(int x,int y,int c) { int sum=0,ans=0; int tx=tp[x],ty=tp[y]; while(tx!=ty) { if(dep[tx]>dep[ty]){swap(x,y);swap(tx,ty);} if(c>=1)ans+=getsum(rt[ys[ty]-1],rt[ys[y]],1,n,1,c); sum+=dep[y]-dep[ty]+1; y=fa[ty];ty=tp[y]; } if(dep[x]>dep[y])swap(x,y); if(c>=1)ans+=getsum(rt[ys[x]-1],rt[ys[y]],1,n,1,c); sum+=dep[y]-dep[x]+1; printf("%d %d\n",sum,ans); } struct change { int x,c; }C[210000];int clen; bool cmp(change n1,change n2){return ys[n1.x]<ys[n2.x];} struct query { int x,y,c; }q[210000];int qlen; int main() { // freopen("message.in","r",stdin); // freopen("message.out","w",stdout); scanf("%d",&n); len=0;memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) { scanf("%d",&fa[i]); if(fa[i]!=0)ins(fa[i],i); } dep[1]=1;pre_tree_node(1); z=0;pre_tree_edge(1,1); trlen=0;memset(rt,0,sizeof(rt)); int m,op,x,y,c; scanf("%d",&m);qlen=0;clen=0; for(int i=1;i<=m;i++) { scanf("%d",&op); if(op==1) { scanf("%d%d%d",&x,&y,&c); qlen++;q[qlen].x=x;q[qlen].y=y;q[qlen].c=i-c-1; } else { scanf("%d",&x); clen++;C[clen].x=x;C[clen].c=i; } } sort(C+1,C+clen+1,cmp); int ctip=1; for(int i=1;i<=z;i++) { if(i==ys[C[ctip].x]) { rt[i]=maketree(rt[i],1,n,C[ctip].c); ctip++; } else {rt[i]=++trlen;tr[trlen].c=0;} rt[i]=merge(rt[i],rt[i-1]); } for(int i=1;i<=qlen;i++) solve(q[i].x,q[i].y,q[i].c); return 0; }
pain and happy in the cruel world.