zoukankan      html  css  js  c++  java
  • bzoj3672/luogu2305 购票 (运用点分治思想的树上cdq分治+斜率优化dp)

    我们都做过一道题(?)货币兑换,是用cdq分治来解决不单调的斜率优化

    现在它放到了树上..

    总之先写下来dp方程,$f[i]=min{f[j]+(dis[i]-dis[j])*p[i]+q[i]} ,j是i的祖先,dis[i]-dis[j]<=l[i]$ ,其中dis[i]表示1号点到i号点的距离

    可以很明显的看出斜率优化,但我们要放到树上做

    于是就运用点分治的思想来找重心(正如普通的cdq是找中点一样)

    步骤是这样的:

    1.对于根为x的一个子树,我们先找到它的重心rt

    2.把rt的子树刨掉,但留下rt,然后递归地再做x,目的是先算出祖先们的答案,为更新孩子们做准备

    3.把rt在子树x中的祖先按深度排序,把rt的子树(不包括rt)按照它们最远能到的祖先的深度排序,然后一边插祖先维护一个凸包,一边给孩子统计答案

    4.递归地做rt的子节点

    斜率优化的细节就不写了(因为全是蒙出来的)

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define ll long long
      4 using namespace std;
      5 const int maxn=2e5+10,inf=0x3f3f3f3f;
      6 
      7 inline ll rd(){
      8     ll x=0;char c=getchar();int neg=1;
      9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     11     return x*neg;
     12 }
     13 
     14 struct Edge{
     15     int b,ne;ll l;
     16 }eg[maxn*2];
     17 int fa[maxn][20],egh[maxn],ect;
     18 int N,NN,dep[maxn],ldep[maxn];
     19 int siz[maxn],root;
     20 int cnt[maxn],tmpl[maxn],tmpr[maxn],pct;
     21 int stk[maxn];
     22 ll dp[maxn],dis[maxn],p[maxn],q[maxn],l[maxn];
     23 bool vis[maxn];
     24 
     25 void dfs1(int x){
     26     int i;
     27     for(i=1;fa[x][i-1]&&fa[fa[x][i-1]][i-1];i++) fa[x][i]=fa[fa[x][i-1]][i-1];
     28     int y=x;for(ll j=l[x];i>=0;i--){
     29         if(fa[y][i]&&dis[y]-dis[fa[y][i]]<=j)
     30             j-=dis[y]-dis[fa[y][i]],y=fa[y][i];
     31     }
     32     if(y!=x) ldep[x]=dep[y];
     33     else ldep[x]=-1;
     34     
     35     for(i=egh[x];i;i=eg[i].ne){
     36         int b=eg[i].b;
     37         dis[b]=dis[x]+eg[i].l;
     38         dep[b]=dep[x]+1;
     39         dfs1(b);
     40     }
     41 }
     42 
     43 void getroot(int x,int smsiz,int &ms,int &root){
     44     siz[x]=1;int mm=0;
     45     for(int i=egh[x];i;i=eg[i].ne){
     46         int b=eg[i].b;if(vis[b]) continue;
     47         getroot(b,smsiz,ms,root);siz[x]+=siz[b];
     48         mm=max(mm,siz[b]);
     49     }mm=max(mm,smsiz-siz[x]);
     50     if(mm<=ms) ms=mm,root=x;
     51 }
     52 void getson(int x){
     53     tmpr[++pct]=x;
     54     for(int i=egh[x];i;i=eg[i].ne){
     55         int b=eg[i].b;if(vis[b]) continue;
     56         getson(b);
     57     }
     58 }
     59 
     60 inline bool cmp(int a,int b){
     61     return ldep[a]>ldep[b];
     62 }
     63 
     64 inline double getk(int a,int b){
     65     return (double)(dp[a]-dp[b])/(dis[a]-dis[b]);
     66 }
     67 
     68 void cdq(int x,int s){
     69     if(s<=1) return;
     70     int rt,ms=inf;
     71     getroot(x,s,ms,rt);
     72     if(x!=rt){
     73         int sms=s,mmm=inf;
     74         for(int i=egh[rt];i;i=eg[i].ne) vis[eg[i].b]=1,sms-=siz[eg[i].b];
     75         cdq(x,sms);
     76     }int l=0;
     77     for(int i=rt;i!=fa[x][0];i=fa[i][0]) tmpl[++l]=i;
     78     pct=0;
     79     for(int i=egh[rt];i;i=eg[i].ne) getson(eg[i].b);
     80     sort(tmpr+1,tmpr+pct+1,cmp);
     81 
     82     int sh=0;
     83     for(int i=1,j=1;i<=pct&&ldep[tmpr[i]]!=-1;i++){
     84         for(;j<=l&&dep[tmpl[j]]>=ldep[tmpr[i]];j++){
     85             while(sh>1&&getk(stk[sh],stk[sh-1])<=getk(stk[sh],tmpl[j])) --sh;
     86             stk[++sh]=tmpl[j];
     87         }
     88         if(sh){
     89             int k=stk[1];
     90             if(sh!=1){
     91                 int a=1,b=sh-1;
     92                 while(a<=b){
     93                     int m=(a+b)>>1;
     94                     if(getk(stk[m],stk[m+1])<=p[tmpr[i]]) k=stk[m],b=m-1;
     95                     else k=stk[m+1],a=m+1;
     96                 }
     97             }
     98             dp[tmpr[i]]=min(dp[tmpr[i]],dp[k]+(dis[tmpr[i]]-dis[k])*p[tmpr[i]]+q[tmpr[i]]);
     99         }
    100     }
    101     for(int i=egh[rt];i;i=eg[i].ne){
    102         cdq(eg[i].b,siz[eg[i].b]);
    103     }
    104 }
    105 
    106 inline void adeg(int a,int b,int l){
    107     eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
    108 }
    109 
    110 int main(){
    111     int i,j,k;
    112     N=rd();rd();
    113     for(i=2;i<=N;i++){
    114         int a=rd(),b=rd();p[i]=rd(),q[i]=rd(),l[i]=rd();
    115         adeg(a,i,b);fa[i][0]=a;
    116     }ldep[0]=-1;dep[1]=1;dfs1(1);
    117     memset(dp,127,sizeof(dp));dp[1]=0;
    118     cdq(1,N);    
    119     for(i=2;i<=N;i++) printf("%lld
    ",dp[i]);
    120     return 0;
    121 }
  • 相关阅读:
    Linux学习33 crontab定时任务语法在线校验 上海
    python测试开发django175.bootstrap导航带下拉菜单的标签页标签页(navtabs) 上海
    python测试开发django172.jQuery 发送请求获取的数据设置为全局变量 上海
    team讨论有感
    蜕变(3)---模式
    uml建模的随想
    Bridge Strategy 和State的区别
    友元在模式中的运用
    Design&Pattern团队《设计模式在软件开发的应用》精华版
    面向对象乱弹(一)
  • 原文地址:https://www.cnblogs.com/Ressed/p/9696185.html
Copyright © 2011-2022 走看看