标签:return 斜率 化凸包 ll Noi2014 int DP define
貌似网上大部分题解都是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 while(l<r&&slope(q[r-1],q[r])>slope(q[r],x)) 33 r--; 34 int res=q[++r]; q[r]=x; 35 return res; 36 } 37 L getans(int x){ 38 int ll=l,rr=r-1; 39 if(l>=r) return q[l]; 40 while(ll<rr){ 41 int mid=(ll+rr+1)>>1; 42 if(slope(q[mid],q[mid+1])<P[x]) ll=mid; 43 else rr=mid-1; 44 } 45 if(slope(q[ll],q[ll+1])<P[x]) 46 return q[ll+1]; 47 return q[ll]; 48 } 49 }; 50 51 struct node{int l,r;tb a;}a[M*3]; 52 void build(int x,int l,int r){ 53 a[x].l=l; a[x].r=r; 54 a[x].a=tb(r-l+1); 55 if(l==r) return; int mid=(l+r)>>1; 56 build(x<<1,l,mid); build(x<<1|1,mid+1,r); 57 } 58 void updata(int x,int k,int id,int lastL[],int lastR[],int lastT[]){ 59 lastL[0]=a[x].a.l; lastR[0]=a[x].a.r; 60 lastT[0]=a[x].a.add(id); 61 if(a[x].l==a[x].r) return; int mid=(a[x].l+a[x].r)>>1; 62 if(k<=mid) updata(x<<1,k,id,lastL+1,lastR+1,lastT+1); 63 else updata(x<<1|1,k,id,lastL+1,lastR+1,lastT+1); 64 } 65 void reset(int x,int k,int lastL[],int lastR[],int lastT[]){ 66 a[x].a.q[a[x].a.r]=lastT[0]; 67 a[x].a.l=lastL[0]; a[x].a.r=lastR[0]; 68 if(a[x].l==a[x].r) return; int mid=(a[x].l+a[x].r)>>1; 69 if(k<=mid) reset(x<<1,k,lastL+1,lastR+1,lastT+1); 70 else reset(x<<1|1,k,lastL+1,lastR+1,lastT+1); 71 } 72 L query(int x,int l,int r,int k){ 73 if(l<=a[x].l&&a[x].r<=r) 74 return getans(k,a[x].a.getans(k)); 75 L mid=(a[x].l+a[x].r)>>1,minn=INF; 76 if(l<=mid) minn=min(minn,query(x<<1,l,r,k)); 77 if(mid<r) minn=min(minn,query(x<<1|1,l,r,k)); 78 return minn; 79 } 80 81 void dfs(int x,int fa,L Dis){ 82 f[x][0]=fa; dep[x]=dep[fa]+1; D[x]=Dis; 83 for(int i=1;i<20;i++) f[x][i]=f[f[x][i-1]][i-1]; 84 int y=jump(x,up[x]); 85 F[x]=query(1,y,dep[x],x); 86 int lastL[20]={0},lastR[20]={0},lastT[20]={0}; 87 updata(1,dep[x],x,lastL,lastR,lastT); 88 for(int i=head[x];i;i=e[i].next) dfs(e[i].u,x,Dis+e[i].v); 89 reset(1,dep[x],lastL,lastR,lastT); 90 } 91 92 int main(){ 93 scanf("%d%d",&n,&t); 94 for(int i=2;i<=n;i++){ 95 L fa,dis; scanf("%lld%lld%lld%lld%lld",&fa,&dis,P+i,Q+i,up+i); 96 add(fa,i,dis); 97 } 98 build(1,1,n); 99 int hh[20]; updata(1,1,1,hh,hh,hh); 100 dep[1]=1; D[0]=-INF; 101 for(int i=head[1];i;i=e[i].next) dfs(e[i].u,1,e[i].v); 102 for(int i=2;i<=n;i++) printf("%lld\n",F[i]); 103 }
标签:return,斜率,化凸包,ll,Noi2014,int,DP,define 来源: https://www.cnblogs.com/xiefengze1/p/10425474.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。