[Noi2014]购票 斜率优化DP+可持久化凸包
貌似网上大部分题解都是CDQ分治+点分治然后再斜率优化DP,我貌似并没有用这个方法。
这一题跟这题有点像,只不过多了一个l的限制
如果说直接跑斜率优化DP,存储整个序列的话,显然是不行的,如图所示(图鸣谢某巨佬)
所以我们需要种一棵线段树,每个线段树内存储一个存当前区间凸包的单调栈,弹出插入操作跟刚刚说的那题一样。
查询的话就查询下整个区间中所有凸包上的最大值就可以了。
时间复杂度:$O(n\log^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\n",F[i]); 110 }