UOJ 55 【WC2014】紫荆花之恋——点分治+平衡树
点分治。在点分树上每个点上用 splay 维护管辖的点的情况。做几次就重构点分树。TLE。只能过 20 分。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } int Mn(int a,int b){return a<b?a:b;} int Mx(int a,int b){return a>b?a:b;} const int N=1e5+5,base=180,K=base+20,M=N*K,mod=1e9;//K not log!!!//K=base+log int n,hd[N],xnt,to[N<<1],nxt[N<<1],w[N<<1],r[N],sz[N],mn,Rt; ll ans; int rt[2][N],tot,c[M][2],vl[M],siz[M],fa[M],pre[N][K],dis[N][K],dep[N]; bool vis[N]; void add(int x,int y,int z){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;} void pshp(int cr){siz[cr]=siz[c[cr][0]]+siz[c[cr][1]]+1;} void rotate(int x) { int y=fa[x],z=fa[y],d=(x==c[y][1]); if(z)c[z][y==c[z][1]]=x; fa[x]=z; fa[c[x][!d]]=y; fa[y]=x; c[y][d]=c[x][!d]; c[x][!d]=y; pshp(y);pshp(x); } void splay(int x) { while(fa[x]) { int y=fa[x],z=fa[y]; if(z) ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y); rotate(x); } } void inst(int &cr,int v,int pr) { if(!cr){cr=++tot;c[cr][0]=c[cr][1]=0;fa[cr]=pr;vl[cr]=v;siz[cr]=1;return;} siz[cr]++; if(v<=vl[cr])inst(c[cr][0],v,cr); else inst(c[cr][1],v,cr); } void ins(int x,int v,bool fx) { inst(rt[fx][x],v,0);splay(tot);rt[fx][x]=tot; } int fnd(int cr,int v) { if(!cr)return -1; int ret=(vl[cr]>=v?fnd(c[cr][0],v):fnd(c[cr][1],v)); if(ret==-1&&vl[cr]>=v)ret=cr; return ret; } void dfsx(int cr) { int ls=c[cr][0],rs=c[cr][1]; printf(" cr=%d(%d %d) c0=%d(%d %d) c1=%d(%d %d)\n", cr,vl[cr],siz[cr],ls,vl[ls],siz[ls],rs,vl[rs],siz[rs]); if(ls)dfsx(ls); if(rs)dfsx(rs); } int qry(int x,int v,bool fx) { int cr=fnd(rt[fx][x],v); if(cr==-1)return 0; splay(cr); rt[fx][x]=cr; return siz[c[cr][1]]+1; } void getrt(int cr,int fa,int s) { sz[cr]=1;int mx=0; for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa) getrt(v,cr,s),sz[cr]+=sz[v],mx=Mx(mx,sz[v]); mx=Mx(mx,s-sz[cr]); if(mx<mn)mn=mx,Rt=cr; } void dfs(int cr,int fa,int d) { pre[cr][++dep[cr]]=Rt;dis[cr][dep[cr]]=d; ins(Rt,r[cr]-d,0);if(dep[cr]>1)ins(Rt,r[cr]-dis[cr][dep[cr]-1],1); for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)dfs(v,cr,d+w[i]); } void solve(int cr,int s) { vis[cr]=1;dfs(cr,0,0); for(int i=hd[cr],v;i;i=nxt[i]) { if(vis[v=to[i]])continue; int ts=(sz[v]<sz[cr]?sz[v]:s-sz[cr]); mn=N;getrt(v,cr,ts);solve(Rt,ts); } } void cz(int s) { tot=0; for(int i=1;i<=s;i++)vis[i]=0;for(int i=1;i<=s;i++)dep[i]=0; for(int i=1;i<=s;i++)rt[0][i]=rt[1][i]=0; mn=N;getrt(1,0,s);solve(Rt,s); } int main() { int bh=rdn();n=rdn();int pr=rdn()%mod,tw=rdn();r[1]=rdn();puts("0"); ins(1,r[1],0);dep[1]=1;dis[1][1]=0;pre[1][1]=1; for(int i=2,T=1;i<=n;i++,T++) { if(T==base)cz(i-1),T=0; pr=rdn()^(ans%mod);tw=rdn();r[i]=rdn(); add(pr,i,tw);add(i,pr,tw); for(int j=1;j<=dep[pr];j++) { pre[i][j]=pre[pr][j];dis[i][j]=dis[pr][j]+tw; ins(pre[i][j],r[i]-dis[i][j],0); if(j>1)ins(pre[i][j],r[i]-dis[i][j-1],1); } dep[i]=dep[pr]+1;pre[i][dep[i]]=i; ins(i,r[i],0);if(dep[i]>1)ins(i,r[i]-dis[i][dep[i]-1],1); for(int j=1;j<dep[i];j++) { int u=pre[i][j],v=pre[i][j+1],d=dis[i][j]-r[i]; ans+=qry(u,d,0); ans-=qry(v,d,1); } printf("%lld\n",ans); } return 0; }
写对拍的话,可以这样生成,就是在 mk.cpp 里调用写好的程序 a.cpp 得到 ans 。可以把 a.cpp 删掉 main 函数改成 a.hpp 。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } int Mn(int a,int b){return a<b?a:b;} int Mx(int a,int b){return a>b?a:b;} const int N=10000,base=180,K=base+20,M=N*K,mod=1e9;//K not log!!!//K=base+log int n,hd[N],xnt,to[N<<1],nxt[N<<1],w[N<<1],r[N],sz[N],mn,Rt; ll ans; int rt[2][N],tot,c[M][2],vl[M],siz[M],fa[M],pre[N][K],dis[N][K],dep[N]; bool vis[N]; void add(int x,int y,int z){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;} void pshp(int cr){siz[cr]=siz[c[cr][0]]+siz[c[cr][1]]+1;} void rotate(int x) { int y=fa[x],z=fa[y],d=(x==c[y][1]); if(z)c[z][y==c[z][1]]=x; fa[x]=z; fa[c[x][!d]]=y; fa[y]=x; c[y][d]=c[x][!d]; c[x][!d]=y; pshp(y);pshp(x); } void splay(int x) { while(fa[x]) { int y=fa[x],z=fa[y]; if(z) ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y); rotate(x); } } void inst(int &cr,int v,int pr) { if(!cr){cr=++tot;c[cr][0]=c[cr][1]=0;fa[cr]=pr;vl[cr]=v;siz[cr]=1;return;} siz[cr]++; if(v<=vl[cr])inst(c[cr][0],v,cr); else inst(c[cr][1],v,cr); } void ins(int x,int v,bool fx) { inst(rt[fx][x],v,0);splay(tot);rt[fx][x]=tot; } int fnd(int cr,int v) { if(!cr)return -1; int ret=(vl[cr]>=v?fnd(c[cr][0],v):fnd(c[cr][1],v)); if(ret==-1&&vl[cr]>=v)ret=cr; return ret; } void dfsx(int cr) { int ls=c[cr][0],rs=c[cr][1]; printf(" cr=%d(%d %d) c0=%d(%d %d) c1=%d(%d %d)\n", cr,vl[cr],siz[cr],ls,vl[ls],siz[ls],rs,vl[rs],siz[rs]); if(ls)dfsx(ls); if(rs)dfsx(rs); } int qry(int x,int v,bool fx) { int cr=fnd(rt[fx][x],v); if(cr==-1)return 0; splay(cr); rt[fx][x]=cr; return siz[c[cr][1]]+1; } void getrt(int cr,int fa,int s) { sz[cr]=1;int mx=0; for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa) getrt(v,cr,s),sz[cr]+=sz[v],mx=Mx(mx,sz[v]); mx=Mx(mx,s-sz[cr]); if(mx<mn)mn=mx,Rt=cr; } void dfs(int cr,int fa,int d) { pre[cr][++dep[cr]]=Rt;dis[cr][dep[cr]]=d; ins(Rt,r[cr]-d,0);if(dep[cr]>1)ins(Rt,r[cr]-dis[cr][dep[cr]-1],1); for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)dfs(v,cr,d+w[i]); } void solve(int cr,int s) { vis[cr]=1;dfs(cr,0,0); for(int i=hd[cr],v;i;i=nxt[i]) { if(vis[v=to[i]])continue; int ts=(sz[v]<sz[cr]?sz[v]:s-sz[cr]); mn=N;getrt(v,cr,ts);solve(Rt,ts); } } void cz(int s) { tot=0; for(int i=1;i<=s;i++)vis[i]=0;for(int i=1;i<=s;i++)dep[i]=0; for(int i=1;i<=s;i++)rt[0][i]=rt[1][i]=0; mn=N;getrt(1,0,s);solve(Rt,s); }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<ctime> #define ll long long #include "a.hpp" using namespace std; const int M1=1000,M2=1000; int main() { srand(time(0));srand(rand()); n=N;//n=rand()%N+1; printf("%d\n%d\n",rand()%20+1,n); r[1]=rand()%M2+1; printf("0 0 %d\n",r[1]); ins(1,r[1],0);dep[1]=1;dis[1][1]=0;pre[1][1]=1; int pr,tw; for(int i=2,T=1;i<=n;i++,T++) { if(T==base)cz(i-1),T=0; pr=rand()%(i-1)+1; tw=rand()%M1+1;r[i]=rand()%M2+1; printf("%lld %d %d\n",pr^(ans%mod),tw,r[i]); add(pr,i,tw);add(i,pr,tw); for(int j=1;j<=dep[pr];j++) { pre[i][j]=pre[pr][j];dis[i][j]=dis[pr][j]+tw; ins(pre[i][j],r[i]-dis[i][j],0); if(j>1)ins(pre[i][j],r[i]-dis[i][j-1],1); } dep[i]=dep[pr]+1;pre[i][dep[i]]=i; ins(i,r[i],0);if(dep[i]>1)ins(i,r[i]-dis[i][dep[i]-1],1); for(int j=1;j<dep[i];j++) { int u=pre[i][j],v=pre[i][j+1],d=dis[i][j]-r[i]; ans+=qry(u,d,0); ans-=qry(v,d,1); } } return 0; }
尝试改一改。设一个 base , 重构点分树只重构不平衡的那部分。再把 splay 的一些操作写成非递归的,就能过 85 分。主要是 r <= 10 的数据过不了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long #define db double #define pb push_back #define ls c[cr][0] #define rs c[cr][1] using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } int Mn(int a,int b){return a<b?a:b;} int Mx(int a,int b){return a>b?a:b;} const int N=1e5+5,K=100,M=N*K,mod=1e9; const db base=0.77; int n,hd[N],xnt,to[N<<1],nxt[N<<1],w[N<<1],r[N],sz[N],mn,Rt; ll ans; int rt[2][N],tot,c[M][2],vl[M],siz[M],fa[M],pre[N][K],dis[N][K],dep[N]; int delpl[M],top; bool vis[N]; vector<int> vt[N]; void add(int x,int y,int z){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;} void pshp(int cr){siz[cr]=siz[c[cr][0]]+siz[c[cr][1]]+1;} void rotate(int x) { int y=fa[x],z=fa[y],d=(x==c[y][1]); if(z)c[z][y==c[z][1]]=x; fa[x]=z; fa[c[x][!d]]=y; fa[y]=x; c[y][d]=c[x][!d]; c[x][!d]=y; pshp(y);pshp(x); } void splay(int x) { for(int y,z;fa[x];rotate(x)) { y=fa[x];z=fa[y]; if(z) ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y); } } int nwnd() { int ret=(top?delpl[top--]:++tot); c[ret][0]=c[ret][1]=0;siz[ret]=1;return ret; } void ins(int x,int v,bool fx,bool nd) { if(!rt[fx][x]){rt[fx][x]=nwnd();vl[rt[fx][x]]=v;fa[rt[fx][x]]=0;return;} int cr=rt[fx][x],pr=0; while(1) { siz[cr]++;pr=cr; if(v<=vl[cr]) { if(!ls){ls=nwnd();fa[ls]=cr;vl[ls]=v;break;} cr=ls; } else { if(!rs){rs=nwnd();fa[rs]=cr;vl[rs]=v;break;} cr=rs; } } if(nd)splay(cr),rt[fx][x]=cr; } void dfs_del(int cr) { delpl[++top]=cr; if(ls)dfs_del(ls);if(rs)dfs_del(rs); } void del(int cr) { dfs_del(rt[0][cr]);if(dep[cr]>1)dfs_del(rt[1][cr]); rt[0][cr]=rt[1][cr]=0; } int fnd(int cr,int v) { int ret=-1; while(cr) { if(vl[cr]>=v)ret=cr,cr=ls; else cr=rs; } return ret; } int qry(int x,int v,bool fx) { int cr=fnd(rt[fx][x],v); if(cr==-1)return 0; splay(cr); rt[fx][x]=cr; return siz[rs]+1; } void getrt(int cr,int fa,int s) { sz[cr]=1;int mx=0; for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa) getrt(v,cr,s),sz[cr]+=sz[v],mx=Mx(mx,sz[v]); mx=Mx(mx,s-sz[cr]); if(mx<mn)mn=mx,Rt=cr; } void dfs(int cr,int fa,int d) { pre[cr][++dep[cr]]=Rt;dis[cr][dep[cr]]=d; vt[Rt].pb(cr); ins(Rt,r[cr]-d,0,1);if(dep[cr]>1)ins(Rt,r[cr]-dis[cr][dep[cr]-1],1,1); for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)dfs(v,cr,d+w[i]); } void solve(int cr,int s) { vis[cr]=1;vt[cr].clear();rt[0][cr]=rt[1][cr]=0; dfs(cr,0,0); for(int i=hd[cr],v;i;i=nxt[i]) { if(vis[v=to[i]])continue; int ts=(sz[v]<sz[cr]?sz[v]:s-sz[cr]); mn=N;getrt(v,cr,ts);solve(Rt,ts); } } void cz(int cr) { int s=vt[cr].size(); for(int i=0,d,t=dep[cr]-1;i<s;i++) {d=vt[cr][i];vis[d]=0;del(d);dep[d]=t;}//t!! mn=N;getrt(cr,0,s);solve(Rt,s); } int main() { int bh=rdn();n=rdn();int pr=rdn()%mod,tw=rdn();r[1]=rdn();puts("0"); ins(1,r[1],0,0);dep[1]=1;dis[1][1]=0;pre[1][1]=1;vt[1].pb(1);vis[1]=1; bh=0; for(int i=2;i<=n;i++) { pr=rdn()^(ans%mod);tw=rdn();r[i]=rdn(); add(pr,i,tw);add(i,pr,tw); for(int j=1,u,v;j<=dep[pr];j++,v=u) { u=pre[i][j]=pre[pr][j];dis[i][j]=dis[pr][j]+tw; ins(u,r[i]-dis[i][j],0,0); if(j>1)ins(u,r[i]-dis[i][j-1],1,0); vt[u].pb(i); if(!bh&&j>1&&vt[u].size()>vt[v].size()*base)bh=v; } dep[i]=dep[pr]+1;pre[i][dep[i]]=i; vis[i]=1; ins(i,r[i],0,0);if(dep[i]>1)ins(i,r[i]-dis[i][dep[i]-1],1,0); vt[i].pb(i); for(int j=1;j<dep[i];j++) { int u=pre[i][j],v=pre[i][j+1],d=dis[i][j]-r[i]; ans+=qry(u,d,0); ans-=qry(v,d,1); } printf("%lld\n",ans); if(bh)cz(bh),bh=0; } return 0; }
然后学习一下 SBT ,还是过不了,有 80 分。于是不想管了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long #define db double #define pb push_back #define ls c[cr][0] #define rs c[cr][1] using namespace std; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } int Mn(int a,int b){return a<b?a:b;} int Mx(int a,int b){return a>b?a:b;} const int N=1e5+5,K=100,M=N*K,mod=1e9; const db base=0.77; int n,hd[N],xnt,to[N<<1],nxt[N<<1],w[N<<1],r[N],sz[N],mn,Rt; ll ans; int rt[2][N],tot,c[M][2],vl[M],siz[M],fa[M],pre[N][K],dis[N][K],dep[N]; int delpl[M],top; bool vis[N]; vector<int> vt[N]; void add(int x,int y,int z){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;w[xnt]=z;} void pshp(int cr){siz[cr]=siz[c[cr][0]]+siz[c[cr][1]]+1;} void rotate(int &cr,int d) { int y=c[cr][!d]; c[cr][!d]=c[y][d]; c[y][d]=cr; pshp(cr); pshp(y); cr=y; } void maintain(int cr,int d) { if(siz[c[c[cr][d]][d]]>siz[cr])rotate(cr,!d); else if(siz[c[c[cr][d]][!d]]>siz[cr])rotate(c[cr][d],d),rotate(cr,!d); else return;/// maintain(ls,0); maintain(rs,1); maintain(cr,0); maintain(cr,1); } int nwnd() { int cr=(top?delpl[top--]:++tot); siz[cr]=1;return cr; } void ins(int &cr,int v,int pr=0) { if(!cr){cr=nwnd();fa[cr]=pr;vl[cr]=v;return;} siz[cr]++; bool d=(v>vl[cr]); ins(c[cr][d],v,cr); maintain(cr,d); } void del(int &cr) { delpl[++top]=cr; if(ls)del(ls);if(rs)del(rs); cr=0; } int qry(int cr,int v) { if(!cr)return 0; if(vl[cr]>=v)return siz[rs]+1+qry(ls,v); return qry(rs,v); } void getrt(int cr,int fa,int s) { sz[cr]=1;int mx=0; for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa) getrt(v,cr,s),sz[cr]+=sz[v],mx=Mx(mx,sz[v]); mx=Mx(mx,s-sz[cr]); if(mx<mn)mn=mx,Rt=cr; } void dfs(int cr,int fa,int d,int t) { pre[cr][++dep[cr]]=Rt;dis[cr][dep[cr]]=d; vt[Rt].pb(cr); ins(rt[0][Rt],r[cr]-d);if(t)ins(rt[1][Rt],r[cr]-dis[cr][t]); for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)dfs(v,cr,d+w[i],t); } void solve(int cr,int s,int t)//t:dep[Rt]-1 { vis[cr]=1;vt[cr].clear();rt[0][cr]=rt[1][cr]=0; dfs(cr,0,0,t); for(int i=hd[cr],v;i;i=nxt[i]) { if(vis[v=to[i]])continue; int ts=(sz[v]<sz[cr]?sz[v]:s-sz[cr]); mn=N;getrt(v,cr,ts);solve(Rt,ts,t+1); } } void cz(int cr) { int s=vt[cr].size(),t=dep[cr]-1;//t!! for(int i=0,d;i<s;i++) {d=vt[cr][i];vis[d]=0;del(rt[0][d]);if(dep[d]>1)del(rt[1][d]);dep[d]=t;} mn=N;getrt(cr,0,s);solve(Rt,s,t); } int main() { int bh=rdn();n=rdn();int pr=rdn()%mod,tw=rdn();r[1]=rdn();puts("0"); ins(rt[0][1],r[1]);dep[1]=1;dis[1][1]=0;pre[1][1]=1;vt[1].pb(1);vis[1]=1; bh=0; for(int i=2;i<=n;i++) { pr=rdn()^(ans%mod);tw=rdn();r[i]=rdn(); add(pr,i,tw);add(i,pr,tw); vis[i]=1; dep[i]=dep[pr]+1; int lm=dep[i];//vis[] for(int j=1,u,v;j<=lm;j++,v=u) { u=pre[i][j]=(j==lm?i:pre[pr][j]); dis[i][j]=(j==lm?0:dis[pr][j]+tw); ins(rt[0][u],r[i]-dis[i][j]); if(j>1)ins(rt[1][u],r[i]-dis[i][j-1]); vt[u].pb(i); if(!bh&&j>1&&vt[u].size()>vt[v].size()*base)bh=v; } for(int j=1,u=pre[i][j],v,d;j<lm;j++,u=v) { v=pre[i][j+1];d=dis[i][j]-r[i]; ans+=qry(rt[0][u],d); ans-=qry(rt[1][v],d); } printf("%lld\n",ans); if(bh)cz(bh),bh=0; } return 0; }