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


      两题都是树分治。

      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 } 
  • 相关阅读:
    Binomial Coeffcients(山东省第二届省赛G题)
    合法的C标示符(判断是否是数字或字母)
    HDU2544最短路问题Floydwarshall Algorithm做法
    简单N的阶乘
    手动实现类的属性
    基本语法基本的数据类型
    UITableViewCell的背景
    基本语法类
    UITableView专题
    单击视图空白处隐藏IPhone键盘
  • 原文地址:https://www.cnblogs.com/fzmh/p/4521198.html
Copyright © 2020-2023  润新知