【填坑向】spoj COT/bzoj2588 Count on a tree
这题是学主席树的时候就想写的,,,
但是当时没写(懒)
现在来填坑
= =日常调半天lca(考虑以后背板)
主席树还是蛮好写的,但是代码出现重复,不太好,导致调试的时候心里没底(虽然事实证明主席树部分没出问题)
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 struct lis{ int x,id;} li[100001]; 5 struct nod{ int num,ls,rs;} t[8000001]; 6 int n,m,x,y,z,sum=0,N=0,lastans=0; 7 int to[200001],nex[200001],list[200001]; 8 int a[100001],h[100001],fir[100001],root[100001],f[100001],pos[100001]; 9 int log[200001],near[200001],rmq[20][200001]; 10 bool operator<(lis a,lis b){ return a.x<b.x;} 11 void add(int x,int y,int z){ to[z]=y;nex[z]=fir[x];fir[x]=z;} 12 inline int lca(int x,int y){ if(x>y) swap(x,y); 13 return (h[rmq[log[y-x+1]][x]]<h[rmq[log[y-x+1]][y-near[y-x+1]+1]])? 14 rmq[log[y-x+1]][x]:rmq[log[y-x+1]][y-near[y-x+1]+1];} 15 void build(int now,int fa) 16 { 17 f[now]=fa;root[now]=++sum; 18 int com=root[fa],cha=root[now],l=1,r=n; 19 while(l<r) 20 if(a[now]>(l+r)/2) 21 l=(l+r)/2+1,t[cha]=(nod){t[com].num+1,t[com].ls,++sum},cha=sum,com=t[com].rs; 22 else 23 r=(l+r)/2,t[cha]=(nod){t[com].num+1,++sum,t[com].rs},cha=sum,com=t[com].ls; 24 list[++N]=now;pos[now]=N;t[cha]=(nod){t[com].num+1,0,0};h[now]=h[fa]+1; 25 for(int i=fir[now];i;i=nex[i]) 26 if(to[i]!=fa) 27 build(to[i],now),list[++N]=now; 28 } 29 void que(int x,int y,int z) 30 { 31 int l=1,r=n,lc=lca(pos[x],pos[y]),lcc=f[lc]; 32 x=root[x],y=root[y],lc=root[lc],lcc=root[lcc]; 33 while(l<r) 34 if(t[t[x].ls].num+t[t[y].ls].num-t[t[lc].ls].num-t[t[lcc].ls].num<z) 35 l=(l+r)/2+1,z-=t[t[x].ls].num+t[t[y].ls].num-t[t[lc].ls].num-t[t[lcc].ls].num, 36 x=t[x].rs,y=t[y].rs,lc=t[lc].rs,lcc=t[lcc].rs; 37 else 38 r=(l+r)/2,x=t[x].ls,y=t[y].ls,lc=t[lc].ls,lcc=t[lcc].ls; 39 lastans=li[l].x; 40 } 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 for(int i=1;i<=n;i++) 45 scanf("%d",&li[i].x),li[i].id=i; 46 sort(li+1,li+n+1); 47 for(int i=1;i<=n;i++) 48 a[li[i].id]=i; 49 for(int i=1;i<n;i++) 50 scanf("%d%d",&x,&y),add(x,y,i),add(y,x,i+n); 51 build(1,0); 52 for(int i=1;i<=N;i++) 53 rmq[0][i]=list[i]; 54 for(int i=1,j=0,k=1;i<=N;log[i]=j,near[i]=k,i++) 55 if(i>k*2) j++,k*=2; 56 for(int i=1,k=2;k<=N;i++,k*=2) 57 for(int j=1;j<=N-k+1;j++) 58 rmq[i][j]=(h[rmq[i-1][j]]<h[rmq[i-1][j+k/2]])?rmq[i-1][j]:rmq[i-1][j+k/2]; 59 for(int i=1;i<=m;i++) 60 scanf("%d%d%d",&x,&y,&z),que(/*lastans^*/x,y,z),printf(i<m?"%d\n":"%d",lastans); 61 return 0; 62 } //lastans^加上以后就是强在,bzoj上的题;不加就是不强在,spoj上的题
顺便吐槽:spoj上内存限制1.5G实在太6,,,
导致我乱开数组,交bzoj的时候MLE了很多发