• bzoj3672 [Noi2014]购票


    推一下式子发现就是普通的斜率优化,但是放到了树上,那么我们怎么做呢,树上有什么能保证复杂度的求路径的算法呢,点分治!

    但是这是有根树,我们对于首先处理点分治后的重心以及与根相连的那个块,之后我们将块中剩余的点按照向上扩展的最大深度排序,深度由大到小插入凸包,注意这里添加的点一定是在块内的,否则复杂度就错了。之后我们再处理其他的块。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <vector>
      7 #define N 205000
      8 #define inf 0x7fffffffffffffff
      9 #define int long long
     10 using namespace std;
     11 int MAX(int a,int b){return a>b?a:b;}
     12 struct point{
     13     int x[2];
     14     point(){}
     15     point(int a,int b){x[0]=a,x[1]=b;}
     16 };
     17 vector <point> v;
     18 double slope(point a,point b)
     19     {return (double)(a.x[1]-b.x[1])/1.0/(a.x[0]-b.x[0]);}
     20 int fa[N],size[N],maxn[N],s[N],p[N],q[N],l[N];
     21 int f[N],dep[N];
     22 int root,sum,vis[N<<1],lk[N];
     23 int e=2,head[N];
     24 struct edge{
     25     int u,v,w,next;
     26 }ed[N<<1];
     27 void add(int u,int v,int w){
     28     ed[e].u=u;ed[e].v=v;ed[e].w=w;
     29     ed[e].next=head[u];head[u]=e++;
     30 }
     31 void insert(int x){
     32     int sz=v.size();
     33     point P=point(dep[x],f[x]);
     34     while(sz>1&&slope(v[sz-2],v[sz-1])<=slope(v[sz-1],P))sz--,v.pop_back();
     35     v.push_back(P);
     36 }
     37 int query(int x){
     38     int l=1,r=v.size()-1,mid,ans=0;
     39     point P=point(1,p[x]);
     40     while(l<=r){
     41         mid=(l+r)>>1;
     42         if(slope(v[mid],v[mid-1])>=p[x])ans=mid,l=mid+1;
     43         else r=mid-1;
     44     }
     45     return v[ans].x[1]+(dep[x]-v[ans].x[0])*p[x]+q[x];
     46 }
     47 void dfs(int x){
     48     for(int i=head[x];i;i=ed[i].next){
     49         int v=ed[i].v;
     50         if(v==fa[x])continue;
     51         dep[v]=dep[x]+ed[i].w;
     52         dfs(v);
     53     }
     54 }
     55 void getroot(int rt,int x){
     56     size[x]=1;maxn[x]=0;
     57     for(int i=head[x];i;i=ed[i].next){
     58         int v=ed[i].v;
     59         if(vis[i])continue;
     60         getroot(rt,v);
     61         size[x]+=size[v];
     62         maxn[x]=MAX(maxn[x],size[v]);
     63     }
     64     maxn[x]=MAX(maxn[x],sum-size[x]);
     65     if(maxn[x]<maxn[root]||(maxn[x]==maxn[root]&&dep[x]<dep[root]))/*puts("??"),*/root=x;
     66 }
     67 int a[N],tot;
     68 void dfs1(int x){
     69     a[++tot]=x;
     70     for(int i=head[x];i;i=ed[i].next){
     71         int v=ed[i].v;
     72         if(vis[i])continue;
     73         dfs1(v);
     74     }
     75 }
     76 bool cmp(int a,int b)
     77     {return dep[a]-l[a]>dep[b]-l[b];}
     78 void work(int rt,int x){
     79     if(sum==1)return ;
     80     for(int i=head[x];i;i=ed[i].next){
     81         int v=ed[i].v;
     82         vis[i]=1;
     83     }
     84     int all=sum,sx=size[x];
     85     if(fa[x]&&!vis[lk[x]]){
     86         sum=size[fa[x]]>sx?all-sx+1:size[fa[x]]+1;
     87         root=0;getroot(rt,rt);work(rt,root);
     88     }
     89     tot=0;
     90     for(int i=head[x];i;i=ed[i].next){
     91         int v=ed[i].v;
     92         dfs1(v);
     93     }
     94     sort(a+1,a+tot+1,cmp);
     95     v.clear();
     96     for(int i=1,j=x;i<=tot;i++){
     97         int now=a[i];
     98         for(;j!=fa[rt]&&dep[j]>=dep[now]-l[now];j=fa[j])insert(j);
     99         if(v.size())f[now]=min(f[now],query(now));
    100     }
    101     for(int i=head[x];i;i=ed[i].next){
    102         int v=ed[i].v;
    103         root=0;sum=size[v]>sx?all-sx:size[v];
    104         getroot(v,v);work(v,root);
    105     }
    106 }
    107 int n,opt;
    108 signed main(){
    109     memset(f,0x3f,sizeof f);
    110     f[1]=0;
    111     scanf("%lld%lld",&n,&opt);
    112     for(int i=2;i<=n;i++){
    113         scanf("%lld%lld%lld%lld%lld",&fa[i],&s[i],&p[i],&q[i],&l[i]);
    114         add(fa[i],i,s[i]);lk[i]=e-1;
    115     }
    116     dfs(1);
    117     root=0;sum=n;maxn[0]=n+1;
    118     getroot(1,1);
    119     work(1,root);
    120     for(int i=2;i<=n;i++)printf("%lld
    ",f[i]);
    121     return 0;
    122 }
    View Code
  • 相关阅读:
    C#控件随窗体大小改变而改变
    Java泛型
    php的stristr()函数,查找字符
    java设计模式之桥梁模式(Bridge)
    怎样从本地删除git远程仓库里面的文件
    VS code 修改主题设置代码对其齐线
    vue+webpack安装sass过程中遇到权限不够,直接删除node_modus文件夹重新安装,node_modus先取得管理员权限才能删
    转:git合并冲突解决方法
    git命令行解决冲突文件步骤
    dos常用命令
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8459830.html
Copyright © 2020-2023  润新知