码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race

时间:2015-05-22 00:22:40      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

  两题都是树分治。

  1758这题可以二分答案avgvalue,因为avgvalue=Σv(e)/s,因此二分后只需要判断Σv(e)-s*avgvalue是否大于等于0,若大于等于0则调整二分下界,否则调整二分上界。假设一棵树树根为x,要求就是经过树根x的最大答案,不经过树根x的可以递归求解。假设B[i]为当前做到的一颗x的子树中的点到x的距离为i的最大权值,A[i]为之前已经做过的所有子数中的点到x的距离为i的最大权值(这里的权值是Σv(e)-i*avgvalue),那么对于当前子树的一个距离i,可以从之前处理的子树中取到树根x距离为L-i到U-i权值中最大的那个,判断B[i]+max(A[L-i],A[U-i])是否大于等于0,这里max(A[L-i],A[U-i])可以用一个单调队列求,每处理完一颗子树用B数组更新A数组。

     2599数据范围在讨论里,比较简单。

代码:

  1 //bzoj1758
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<map>
  5 #include<cstring>
  6 #include<vector>
  7 #include<cmath>
  8 #include<string>
  9 #define N 500010
 10 #define M 1010
 11 using namespace std;
 12 double ans,A[N],B[N],P;
 13 int AS,BS;
 14 int pre[N],p[N],tt[N],ww[N],dp,n,L,U,a,b,c,father[N],s[N],flag[N],tmproot,i,j,l,r,f[N];
 15 double left,right,mid;
 16 void link(int x,int y,int z)
 17 {
 18     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;ww[dp]=z;
 19 }
 20 void getroot(int x,int fa,int sum)
 21 {
 22     int i,f=0;
 23     i=p[x];
 24     father[x]=fa;
 25     s[x]=1;
 26     while (i)
 27     {
 28         if ((tt[i]!=fa)&&(!flag[tt[i]]))
 29         {
 30             getroot(tt[i],x,sum);
 31             s[x]=s[x]+s[tt[i]];
 32             if (s[tt[i]]>sum/2) f=1;
 33         }
 34         i=pre[i];
 35     }
 36     if (sum-s[x]>sum/2) f=1;
 37     if (f==0) tmproot=x;
 38 }
 39 void dfs(int x,int fa,int deep,double value)
 40 {
 41     int i;
 42     i=p[x];
 43     B[deep]=max(B[deep],value-mid*double(deep));
 44     BS=max(deep,BS);
 45     while (i)
 46     {
 47         if ((tt[i]!=fa)&&(!flag[tt[i]]))
 48             dfs(tt[i],x,deep+1,value+ww[i]);
 49         i=pre[i];
 50     }
 51 }
 52 void work(int x,int sum)
 53 {
 54     int i,root,ti,ff;
 55     getroot(x,0,sum);
 56     root=tmproot;
 57     flag[root]=1;
 58     i=p[root];
 59     while (i)
 60     {
 61         if (!flag[tt[i]])
 62         {
 63             if (father[root]!=tt[i])
 64             work(tt[i],s[tt[i]]);
 65             else
 66             work(tt[i],sum-s[root]);
 67         }
 68         i=pre[i];
 69     }
 70 //----------------------------------
 71     left=0;right=1000000;ti=0;
 72     while (ti<=35)
 73     {
 74         ti++;
 75         mid=(left+right)/2;
 76         ff=0;
 77         for (i=1;i<=AS;i++)
 78         A[i]=P;AS=0;
 79         i=p[root];
 80         while (i)
 81         {
 82         if (!flag[tt[i]])
 83         {
 84             for (j=1;j<=BS;j++)
 85             B[j]=P;BS=0;
 86             dfs(tt[i],0,1,ww[i]);
 87             r=0;l=1;
 88             for (j=min(U-1,AS);j>=L;j--)
 89             {
 90                 r++;f[r]=j;
 91                 while ((l<r)&&(A[f[r]]>=A[f[r-1]])) 
 92                 {
 93                     f[r-1]=f[r];
 94                     r--; 
 95                 } 
 96             }
 97             for (j=1;j<=BS;j++)
 98             {
 99                 
100                 if ((L<=j)&&(j<=U))
101                 if (B[j]>=0) ff=1;
102                 
103                 while ((l<=r)&&(f[l]+j>U)) l++;
104                 if (L-j>0)
105                 {
106                     r++;f[r]=L-j;
107                     while ((l<r)&&(A[f[r]]>=A[f[r-1]])) 
108                     {
109                         f[r-1]=f[r];
110                         r--;
111                     }
112                     if (A[f[l]]+B[j]>=0) ff=1;
113                 }
114             }
115             for (j=1;j<=BS;j++)
116             A[j]=max(A[j],B[j]);
117             AS=max(AS,BS);
118         }
119         if (ff) break;
120         i=pre[i];
121         }
122     
123         if (ff) left=mid;else right=mid;
124     }
125     ans=max(ans,left);
126     flag[root]=0;
127 }
128 int main()
129 {
130     scanf("%d",&n);
131     scanf("%d%d",&L,&U);
132     P=1000000;
133     P=-P*P;
134     for (i=1;i<=n-1;i++)
135     {
136         scanf("%d%d%d",&a,&b,&c);
137         link(a,b,c);
138         link(b,a,c);
139     }
140     for (i=1;i<=n;i++)
141     {
142         A[i]=P;
143         B[i]=P;
144     }
145     ans=0;
146     work(1,n);
147     printf("%.3lf",ans);
148 } 
  1 //bzoj2599
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<map>
  5 #include<cstring>
  6 #include<vector>
  7 #include<cmath>
  8 #include<string>
  9 #define N 1000010
 10 #define M 1010
 11 #define P 1000000007
 12 using namespace std;
 13 int i,j,p[N],tt[N],s[N],father[N],ww[N],pre[N],tmproot,n,m;
 14 int dp,flag[N],a,b,c,f[N],g[N],AS,BS,A[N],B[N],ans;
 15 void link(int x,int y,int z)
 16 {
 17     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;ww[dp]=z;
 18 }
 19 void getroot(int x,int fa,int sum)
 20 {
 21     int i,f=0;
 22     i=p[x];
 23     father[x]=fa;
 24     s[x]=1;
 25     while (i)
 26     {
 27         if ((tt[i]!=fa)&&(!flag[tt[i]]))
 28         {
 29             getroot(tt[i],x,sum);
 30             s[x]=s[x]+s[tt[i]];
 31             if (s[tt[i]]>sum/2) f=1;
 32         }
 33         i=pre[i];
 34     }
 35     if (sum-s[x]>sum/2) f=1;
 36     if (f==0) tmproot=x;
 37 }
 38 void dist(int x,int fa,int deep,int value)
 39 {
 40     int i;
 41     i=p[x];
 42     if (value<=m)
 43     {
 44         if (g[value]==0x37373737)
 45         {
 46             BS++;
 47             B[BS]=value;
 48         }
 49         g[value]=min(g[value],deep);
 50     }
 51     else
 52     return;
 53     while (i)
 54     {
 55         if ((tt[i]!=fa)&&(!flag[tt[i]]))
 56             dist(tt[i],x,deep+1,value+ww[i]);
 57         i=pre[i];
 58     }
 59     
 60 }
 61 void work(int x,int sum)
 62 {
 63     int i,root;
 64     getroot(x,0,sum);
 65     root=tmproot;
 66     flag[root]=1;
 67     i=p[root];
 68     while (i)
 69     {
 70         if (!flag[tt[i]])
 71         {
 72             if (tt[i]==father[root])
 73             work(tt[i],sum-s[root]);
 74             else
 75             work(tt[i],s[tt[i]]);
 76         }
 77         i=pre[i];
 78     }
 79     //-----------------------------
 80     for (i=1;i<=AS;i++)
 81     f[A[i]]=0x37373737;AS=0;
 82     i=p[root];
 83     while (i)
 84     {
 85         if (!flag[tt[i]])
 86         {
 87             for (j=1;j<=BS;j++)
 88             g[B[j]]=0x37373737;BS=0;
 89             dist(tt[i],0,1,ww[i]);
 90             for (j=1;j<=BS;j++)
 91             ans=min(ans,g[B[j]]+f[m-B[j]]);
 92             for (j=1;j<=BS;j++)
 93             if (f[B[j]]==0x37373737)
 94             {
 95                 AS++;A[AS]=B[j];
 96             }
 97             for (j=1;j<=BS;j++)
 98             f[B[j]]=min(f[B[j]],g[B[j]]);
 99         }
100         i=pre[i];
101     }
102     flag[root]=0;
103 }
104 int main()
105 {
106     scanf("%d%d",&n,&m);
107     for (i=1;i<=n-1;i++)
108     {
109         scanf("%d%d%d",&a,&b,&c);
110         a++;b++;
111         link(a,b,c);
112         link(b,a,c);
113     }
114     for (i=1;i<=m;i++)
115     {
116         f[i]=0x37373737;
117         g[i]=f[i];
118     }
119     ans=0x37373737;
120     work(1,n);
121     if (ans!=0x37373737)
122     printf("%d",ans);
123     else
124     printf("-1");
125 } 

 

bzoj1758 [Wc2010]重建计划 & bzoj2599 [IOI2011]Race

标签:

原文地址:http://www.cnblogs.com/fzmh/p/4521198.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!