zoukankan      html  css  js  c++  java
  • [Noi2014]购票 斜率优化DP+可持久化凸包

    貌似网上大部分题解都是CDQ分治+点分治然后再斜率优化DP,我貌似并没有用这个方法。

    这一题跟这题有点像,只不过多了一个l的限制

    如果说直接跑斜率优化DP,存储整个序列的话,显然是不行的,如图所示(图鸣谢某巨佬

    所以我们需要种一棵线段树,每个线段树内存储一个存当前区间凸包的单调栈,弹出插入操作跟刚刚说的那题一样。

    查询的话就查询下整个区间中所有凸包上的最大值就可以了。

    时间复杂度:$O(nlog^2 n)$。写起来并不算很困难。

      1 #include<bits/stdc++.h>
      2 #define M 200005
      3 #define L long long
      4 #define INF (1LL<<62)
      5 using namespace std;
      6 
      7 struct edge{int u,v,next;}e[M]={0}; int head[M]={0},use=0;
      8 void add(int x,int y,int z){use++;e[use].u=y;e[use].v=z;e[use].next=head[x];head[x]=use;}
      9 L D[M]={0},P[M]={0},Q[M]={0},F[M]={0},n,t,up[M]={0};
     10 double slope(int i,int j){return 1.*(F[i]-F[j])/(D[i]-D[j]);}
     11 L getans(int x,int y){if(y==0) return INF; return F[y]+(D[x]-D[y])*P[x]+Q[x];}
     12 
     13 int f[M][20]={0},dep[M]={0};
     14 int jump(int x,L dis){
     15     for(int i=19;~i;i--)
     16     if(D[x]-D[f[x][i]]<=dis){
     17         dis-=D[x]-D[f[x][i]];
     18         x=f[x][i];
     19     }
     20     return max(1,dep[x]);
     21 }
     22 
     23 struct tb{
     24     int *q,l,r;
     25     tb(){l=1; r=0; q=NULL;}
     26     tb(int len){
     27         q=new int[len+5];
     28         memset(q,0,sizeof(int )*(len+5));
     29         l=1; r=0;
     30     }
     31     int add(int x){
     32         int ll=l,rr=r-1;
     33         if(l<r){
     34             while(ll<rr){
     35                 int mid=(ll+rr)>>1;
     36                 if(slope(q[mid],q[mid+1])>slope(q[mid+1],x)) rr=mid;
     37                 else ll=mid+1;
     38             }
     39             if(slope(q[ll],q[ll+1])<slope(q[ll+1],x)) ll++;
     40             r=ll;
     41         }
     42         int res=q[++r]; q[r]=x;
     43         return res;
     44     }
     45     L getans(int x){
     46         int ll=l,rr=r-1;
     47         if(l>=r) return q[l];
     48         while(ll<rr){
     49             int mid=(ll+rr+1)>>1;
     50             if(slope(q[mid],q[mid+1])<P[x]) ll=mid;
     51             else rr=mid-1;
     52         }
     53         if(slope(q[ll],q[ll+1])<P[x]) 
     54         return q[ll+1];
     55         return q[ll];
     56     }
     57 };
     58 
     59 struct node{int l,r;tb a;}a[M*3];
     60 void build(int x,int l,int r){
     61     a[x].l=l; a[x].r=r;
     62     a[x].a=tb(r-l+1);
     63     if(l==r) return; int mid=(l+r)>>1;
     64     build(x<<1,l,mid); build(x<<1|1,mid+1,r);
     65 }
     66 void updata(int x,int k,int id,int lastL[],int lastR[],int lastT[]){
     67     lastL[0]=a[x].a.l; lastR[0]=a[x].a.r;
     68     lastT[0]=a[x].a.add(id);
     69     if(a[x].l==a[x].r) return; int mid=(a[x].l+a[x].r)>>1;
     70     if(k<=mid) updata(x<<1,k,id,lastL+1,lastR+1,lastT+1);
     71     else updata(x<<1|1,k,id,lastL+1,lastR+1,lastT+1);
     72 }
     73 void reset(int x,int k,int lastL[],int lastR[],int lastT[]){
     74     a[x].a.q[a[x].a.r]=lastT[0];
     75     a[x].a.l=lastL[0]; a[x].a.r=lastR[0];
     76     if(a[x].l==a[x].r) return; int mid=(a[x].l+a[x].r)>>1;
     77     if(k<=mid) reset(x<<1,k,lastL+1,lastR+1,lastT+1);
     78     else reset(x<<1|1,k,lastL+1,lastR+1,lastT+1);
     79 }
     80 L query(int x,int l,int r,int k){
     81     if(l<=a[x].l&&a[x].r<=r) 
     82     return getans(k,a[x].a.getans(k));
     83     L mid=(a[x].l+a[x].r)>>1,minn=INF;
     84     if(l<=mid) minn=min(minn,query(x<<1,l,r,k));
     85     if(mid<r) minn=min(minn,query(x<<1|1,l,r,k));
     86     return minn;
     87 }
     88 
     89 void dfs(int x,int fa,L Dis){
     90     f[x][0]=fa; dep[x]=dep[fa]+1; D[x]=Dis;
     91     for(int i=1;i<20;i++) f[x][i]=f[f[x][i-1]][i-1];
     92     int y=jump(x,up[x]);
     93     F[x]=query(1,y,dep[x],x);
     94     int lastL[20]={0},lastR[20]={0},lastT[20]={0};
     95     updata(1,dep[x],x,lastL,lastR,lastT);
     96     for(int i=head[x];i;i=e[i].next) dfs(e[i].u,x,Dis+e[i].v);
     97     reset(1,dep[x],lastL,lastR,lastT);
     98 }
     99 int main(){
    100     scanf("%d%d",&n,&t);
    101     for(int i=2;i<=n;i++){
    102         L fa,dis; scanf("%lld%lld%lld%lld%lld",&fa,&dis,P+i,Q+i,up+i);
    103         add(fa,i,dis);
    104     }
    105     build(1,1,n);
    106     int hh[20]; updata(1,1,1,hh,hh,hh);
    107     dep[1]=1; D[0]=-INF; 
    108     for(int i=head[1];i;i=e[i].next) dfs(e[i].u,1,e[i].v);
    109     for(int i=2;i<=n;i++) printf("%lld
    ",F[i]);
    110 }
  • 相关阅读:
    Android layout属性大全
    如何看懂Code128条形码
    二维码
    在线条形码生成器
    GS1已分配给国家(地区)编码组织的前缀码
    POJ 3321 Apple Tree DFS序+fenwick
    bootstrap之WaitForIdle&amp;&amp;Clear
    ubuntu14操作系统chrome标签和书签乱码解决
    动态规划-hdoj-4832-百度之星2014初赛第二场
    截取符合指数分布的一部分样本的理论与实验
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10425474.html
Copyright © 2011-2022 走看看