[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 }
View Code

 

posted @ 2016-06-19 11:58  czllgzmzl  阅读(243)  评论(0编辑  收藏  举报