zoukankan      html  css  js  c++  java
  • bzoj 4860 [BeiJing2017]树的难题

    题面

    https://www.lydsy.com/JudgeOnline/problem.php?id=4860

    题解

    点分治

    设当前重心为v

    假设已经把所有边按照出发点第一关键字, 颜色第二关键字排序

    对于当前的v 我们顺次考虑他的出边

    设当前出边(v,nw) 颜色 col

    我们枚举nw的出边

    对于一条nw的出边而言, 分为两种情况

    1. 颜色与col相同   用线段树维护深度及对应的最值,查询到最大值即可 (v,nw)没有贡献

    2. 颜色与col不同   用另一棵线段树维护深度以及与(当前节点的连向其父节点的边的颜色)不同的(连向子节点的边)所对应的子节点对应的子树之内的最值 加上col的权值

    向上的时候 将线段树合并

    Code

      1 #include <cstdio>
      2 #include <cctype>
      3 #include <algorithm>
      4 const int maxn=400010,inf=2000000010;
      5 int ans,n,x,y,z,i,m,l,r,c[maxn*3],cnt;
      6 inline int max(int a,int b){
      7     return a>b?a:b; 
      8 }
      9 inline void up(int&a,const int&b){
     10     if(a<b)a=b;
     11 }
     12 inline int getint(){
     13     char c=getchar();
     14     int x=0,neg=1;
     15     while(!isdigit(c)){
     16         if(c=='-')neg=-1;
     17         c=getchar();
     18     }
     19     while(isdigit(c)){
     20         x=x*10+c-48;
     21         c=getchar();
     22     }
     23     return x*neg;
     24 }
     25 struct edge{
     26     int from,to,color;
     27 }e[maxn<<1];
     28 struct data{
     29     int dep,sum;
     30 };
     31 struct node{
     32     int v,lc,rc;
     33 }a[maxn*5];
     34 int merge(int x,int y){
     35     if(!x || !y )return x|y;
     36     a[x].lc=merge(a[x].lc,a[y].lc);
     37     a[x].rc=merge(a[x].rc,a[y].rc);
     38     up(a[x].v,a[y].v);
     39     return x;
     40 }
     41 void add(int&i,int rl,int rr,int x,int v){
     42     if(!i)a[i=++cnt]=(node){v,0,0};
     43         else up(a[i].v,v);
     44     if(rl<rr){
     45         int m=(rl+rr)>>1;
     46         if(x>m)add(a[i].rc,m+1,rr,x,v);
     47             else add(a[i].lc,rl,m,x,v);
     48     }
     49 }
     50 int query(int i,int rl,int rr,int l,int r){
     51     if(!i)return -inf;
     52     if(rl==l && rr==r)return a[i].v;
     53     int m=(rl+rr)>>1;
     54     if(l>m)return query(a[i].rc,m+1,rr,l,r);
     55         else if(r<=m)return query(a[i].lc,rl,m,l,r);
     56             else return max(query(a[i].lc,rl,m,l,m),query(a[i].rc,m+1,rr,m+1,r));
     57 }
     58 struct tree{
     59     int xb,h[maxn],n,size[maxn],f[maxn],rt,sum,dep[maxn],ll,ss[maxn];
     60     bool b[maxn];
     61     data w[maxn];
     62     void addedge(int x,int y,int z){
     63         e[++xb]=(edge){y,x,z};
     64         e[++xb]=(edge){x,y,z};
     65     }
     66     void dfs(int x,int fa){
     67         size[x]=f[x]=1;
     68         for(int i=h[x];i<h[x+1];++i){
     69             int y=e[i].to;
     70             if(y!=fa && !b[y]){
     71                 dfs(y,x);
     72                 size[x]+=size[y];
     73                 up(f[x],size[y]);
     74             }
     75         }
     76         up(f[x],sum-size[x]);
     77         if(f[rt]>f[x])rt=x;
     78     }
     79     void got(int x,int fa,int dep,int color,int sum){
     80         for(int y,i=h[x];i<h[x+1];++i){
     81             y=e[i].to;
     82             if(y!=fa && !b[y]){
     83                 if(e[i].color==color)w[++ll]=(data){dep+1,sum};
     84                     else w[++ll]=(data){dep+1,sum+c[e[i].color]};
     85                 got(e[i].to,x,dep+1,e[i].color,w[ll].sum);
     86             }
     87         }
     88     }
     89     void solve(int x){
     90         b[x]=1;
     91         int i,rt1=0,rt2=cnt=0,j;
     92         for(i=h[x];i<h[x+1];++i){   
     93             if(i>h[x] && e[i].color>e[i-1].color)rt1=merge(rt1,rt2),rt2=0;         
     94             if(!b[e[i].to]){
     95                 w[ll=1]=(data){1,c[e[i].color]};
     96                 got(e[i].to,x,1,e[i].color,c[e[i].color]);
     97                 ss[i]=ll;
     98                 for(j=1;j<=ll;++j)if(w[j].dep<=r){
     99                     if(w[j].dep>=l)up(ans,w[j].sum);
    100                     if(w[j].dep<r){
    101                         up(ans,query(rt1,1,n,max(1,l-w[j].dep),r-w[j].dep)+w[j].sum);
    102                         up(ans,query(rt2,1,n,max(1,l-w[j].dep),r-w[j].dep)-c[e[i].color]+w[j].sum);
    103                     }
    104                 }
    105                 for(j=1;j<=ll;++j)if(w[j].dep<=r)add(rt2,1,n,w[j].dep,w[j].sum);
    106             }
    107         }
    108         for(i=h[x];i<h[x+1];++i)
    109             if(!b[e[i].to]){
    110                 sum=ss[i];
    111                 rt=0;
    112                 dfs(e[i].to,x);
    113                 solve(rt);
    114             }
    115     }
    116 }t;
    117 bool cmp(const edge&a,const edge&b){
    118     return a.from==b.from?a.color<b.color:a.from<b.from;
    119 }
    120 int main(){
    121     //freopen("input","r",stdin);
    122     a[0].v=-inf;
    123     t.n=n=getint();
    124     m=getint();
    125     l=getint();
    126     r=getint();
    127     for(i=1;i<=m;++i)c[i]=getint();
    128     for(i=1;i<n;++i){
    129         x=getint();
    130         y=getint();
    131         z=getint();
    132         t.addedge(x,y,z);
    133     }
    134     std::sort(e+1,e+((n-1)*2)+1,cmp);
    135     for(i=1;i<=((n-1)<<1);++i)
    136         if(!t.h[e[i].from])t.h[e[i].from]=i;
    137     t.h[n+1]=(n-1)<<1|1; 
    138     t.f[t.rt=0]=inf;
    139     t.sum=n;
    140     ans=-inf;
    141     t.dfs(1,0);
    142     t.solve(t.rt);
    143     printf("%d
    ",ans);
    144 }
    View Code

    Review

    一开始以为是树形dp 后来发现那是错的

    还可以用单调队列过 好像更简单

  • 相关阅读:
    文件管理
    权限管理
    用户和用户组
    BZOJ2957: 楼房重建(线段树&LIS)
    BZOJ2938: [Poi2000]病毒(AC自动机)
    BZOJ2935: [Poi1999]原始生物(欧拉回路)
    BZOJ4033: [HAOI2015]树上染色(树形DP)
    LightOJ
    LightOJ
    BZOJ4917: [Lydsy1706月赛]Hash Killer IV(模拟)
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9347210.html
Copyright © 2011-2022 走看看