[bzoj2117] [2010国家集训队]Crash的旅游计划
静态信息的点分治。
老套路,对各个重心用数据结构维护所管辖的点到它的距离。。再去重一波
查询的时候就直接二分了。。如果数据结构用动态开点的线段树的话就可以直接在线段树上找了..不过我还是写了treap
时间复杂度O(nlog^3n)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 using namespace std; 6 const int maxn=100233,mxnode=maxn*20*2; 7 struct zs{ 8 int too,pre,dis; 9 }e[maxn<<1];int tot,last[maxn]; 10 int sz[mxnode],mx[mxnode],lc[mxnode],rc[mxnode],val[mxnode],rnd[mxnode],tt; 11 int f[maxn][20],g[maxn][20],dis[maxn][20]; 12 int rt[maxn<<1],st[maxn],top,tmp[maxn],size[maxn],mxdep[maxn]; 13 bool del[maxn]; 14 int i,j,k,n,m,V,root,kk,POI; 15 16 int ra;char rx; 17 inline int read(){ 18 rx=getchar(),ra=0; 19 while(rx<'0'||rx>'9')rx=getchar(); 20 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 21 } 22 23 void getrt(int x,int fa){ 24 size[x]=1,mx[x]=0; 25 for(int i=last[x];i;i=e[i].pre)if(!del[e[i].too]&&e[i].too!=fa) 26 getrt(e[i].too,x),size[x]+=size[e[i].too],mx[x]=max(mx[x],size[e[i].too]); 27 mx[x]=max(mx[x],POI-size[x]); 28 if(mx[x]<mx[root])root=x; 29 } 30 void getpoi(int x,int fa){ 31 for(int i=last[x];i;i=e[i].pre) 32 if(!del[e[i].too]&&e[i].too!=fa)st[++top]=e[i].too,tmp[e[i].too]=tmp[x]+e[i].dis,getpoi(e[i].too,x); 33 } 34 inline void upd(int x){sz[x]=sz[lc[x]]+1+sz[rc[x]];} 35 inline void lturn(int &x){int R=rc[x];rc[x]=lc[R],lc[R]=x,sz[R]=sz[x],upd(x),x=R;} 36 inline void rturn(int &x){int L=lc[x];lc[x]=rc[L],rc[L]=x,sz[L]=sz[x],upd(x),x=L;} 37 void insert(int &x){ 38 if(!x){x=++tt,sz[x]=1,val[x]=V,rnd[x]=rand()+(tt&rand());return;} 39 sz[x]++; 40 if(V<=val[x]){ 41 insert(lc[x]); 42 if(rnd[lc[x]]<rnd[x])rturn(x); 43 }else{ 44 insert(rc[x]); 45 if(rnd[rc[x]]<rnd[x])lturn(x); 46 } 47 } 48 inline int query(int x){ 49 int sm=0; 50 while(x){ 51 if(V<=val[x])x=lc[x];else 52 if(V>val[x])sm+=sz[lc[x]]+1,x=rc[x]; 53 } 54 return sm; 55 } 56 57 void work(int x,int dep){ 58 root=0,getrt(x,0), 59 st[top=1]=x,getpoi(x,0); 60 register int i; 61 for(i=1;i<=top;i++)V=tmp[st[i]],insert(rt[root+n]); 62 for(i=1;i<=top;i++)g[st[i]][dep]=rt[root+n]; 63 top=tmp[root]=0,getpoi(root,0); 64 for(i=1;i<=top;i++)V=tmp[st[i]],insert(rt[root]); 65 for(i=1;i<=top;i++)f[st[i]][dep]=rt[root],dis[st[i]][dep]=tmp[st[i]]; 66 f[root][dep]=rt[root]; 67 del[root]=1,mxdep[root]=dep; 68 for(i=last[root];i;i=e[i].pre)if(!del[e[i].too])POI=size[e[i].too],work(e[i].too,dep+1); 69 } 70 bool check(int x,int mid){ 71 V=mid; 72 int sm=query(f[x][mxdep[x]]),i; 73 for(i=1;i<mxdep[x]&&sm<kk;i++)if(mid>dis[x][i]) 74 sm++, 75 V=mid-dis[x][i], 76 sm+=query(f[x][i])-query(g[x][i+1]); 77 return sm>=kk; 78 } 79 80 inline void insert(int a,int b,int c){ 81 e[++tot].too=b,e[tot].dis=c,e[tot].pre=last[a],last[a]=tot; 82 e[++tot].too=a,e[tot].dis=c,e[tot].pre=last[b],last[b]=tot; 83 } 84 int main(){ 85 mx[0]=1e9+233,srand(2333); 86 n=read(),kk=read();int mx=0; 87 for(i=1;i<n;i++)j=read(),k=read(),insert(j,k,read()); 88 POI=n,work(1,1); 89 for(i=1;i<tot;i+=2)mx+=e[i].dis; 90 for(i=1;i<=n;i++){ 91 int l=1,r=mx,mid; 92 while(l<r){ 93 mid=l+r+1>>1; 94 if(check(i,mid))r=mid-1;else l=mid; 95 } 96 printf("%d\n",l); 97 } 98 return 0; 99 }