bzoj4538: [Hnoi2016]网络
被肉老师d得血肉模糊
上午自己yy了一发dfs序+树状数组+cdq,结果发现自己子树里面的情况是处理不了的...(orz claris KDT踩过
正解就是整体二分,然后每次像扫描线一样扫过,就能解决时间问题啦
主要的问题是判断是否有一条路径不经过当前点
转化成判断是否所有路径都经过当前点,我们进行如下操作:
对于每一条路径,dfs序以后,两个端点+1,公共祖先-1,公共祖先的父亲-1
然后我们可以发现,假如一条路径不经过当前点,对当前点的贡献就是0,否则就是1
这样就可以logn判出来了
LCA可以O(1) (然而对复杂度计算没什么区别,都是O(nlog^2n))
rose:常数巨大
#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[110000]; 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[110000],dep[110000]; int z,L[110000],R[110000];//用于计算子树权值和 int u,ys[110000],f[30][210000];//用于求LCA void dfs(int x) { L[x]=++z;f[0][++u]=x;ys[x]=u; 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; dfs(y); f[0][++u]=x; } } R[x]=z; } //~~~~~~~~~~~~~~~~~~~ys~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int Bin[30],Log[210000]; void get_st() { Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2; Log[1]=0;for(int i=2;i<=u ;i++)Log[i]=Log[i/2]+1; dep[0]=(1<<30); for(int j=1;j<=25;j++) for(int i=1;i+Bin[j]-1<=u;i++) if(dep[f[j-1][i]]<dep[f[j-1][i+Bin[j-1]]])f[j][i]=f[j-1][i]; else f[j][i]=f[j-1][i+Bin[j-1]]; } int LCA(int x,int y) { if(ys[x]>ys[y])swap(x,y); x=ys[x];y=ys[y]; int k=Log[y-x+1]; if(dep[f[k][x]]<dep[f[k][y-Bin[k]+1]])return f[k][x]; else return f[k][y-Bin[k]+1]; } //~~~~~~~~~~~~~~~~~~~LCA~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //------------------------------------------init------------------------------------------------------------ int n,s[110000]; int lowbit(int x){return x&-x;} void change(int x,int k){ while(x<=n+10){s[x]+=k;x+=lowbit(x);} } int getsum(int x){ int ret=0; while(x>0){ret+=s[x];x-=lowbit(x);} return ret; } //~~~~~~~~~~~~~~~~~~~~bit~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ struct qnode{int op,x,y,d,t;}q[410000],lq[410000],rq[410000];int cnt,as[210000]; void erfen(int l,int r,int st,int ed) { if(l>r)return ; if(st>ed)return ; int mid=(l+r)/2,e=0,llen=0,rlen=0; for(int i=st;i<=ed;i++) { if(q[i].op==0) { if(q[i].d>=mid) { e++; int lca=LCA(q[i].x,q[i].y); change(L[q[i].x],1),change(L[q[i].y],1); change(L[lca],-1); if(fa[lca]!=0)change(L[fa[lca]],-1); rq[++rlen]=q[i]; } else lq[++llen]=q[i]; } else if(q[i].op==1) { if(q[i].d>=mid) { e--; int lca=LCA(q[i].x,q[i].y); change(L[q[i].x],-1),change(L[q[i].y],-1); change(L[lca],1); if(fa[lca]!=0)change(L[fa[lca]],1); rq[++rlen]=q[i]; } else lq[++llen]=q[i]; } else { int d=getsum(R[q[i].x])-getsum(L[q[i].x]-1); if(d==e)lq[++llen]=q[i]; else rq[++rlen]=q[i],as[q[i].y]=mid; } } for(int i=1;i<=llen;i++)q[st+i-1]=lq[i]; for(int i=1;i<=rlen;i++)q[st+llen+i-1]=rq[i]; erfen(l,mid-1,st,st+llen-1); erfen(mid+1,r,st+llen,ed); } //---------------------------------------------------------------------------------------- bool b[210000]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int Q,x,y; scanf("%d%d",&n,&Q); len=0;memset(last,0,sizeof(last)); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); ins(x,y),ins(y,x); } dep[1]=1;fa[1]=0;dfs(1); get_st(); cnt=0;int mmax=0; memset(b,false,sizeof(b)); for(int i=1;i<=Q;i++) { scanf("%d",&q[i].op);q[i].t=i; if(q[i].op==0) { scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].d),q[i].d++; mmax=max(mmax,q[i].d); if(q[i].x>q[i].y)swap(q[i].x,q[i].y); } else if(q[i].op==1) { scanf("%d",&x);b[x]=true; q[i].x=q[x].x,q[i].y=q[x].y,q[i].d=q[x].d; } else scanf("%d",&q[i].x),q[i].y=++cnt; } int qq=Q+1; for(int i=1;i<=Q;i++) if(q[i].op==0&&b[i]==false) { q[++Q]=q[i]; q[Q].op=1,q[Q].t=qq; } erfen(1,mmax,1,Q); for(int i=1;i<=cnt;i++) printf("%d\n",as[i]-1); return 0; }
pain and happy in the cruel world.