1 条题解
-
0
糖飞了,题目是 0-index 所以修改操作的 是要少加一个的。
这题就是分块维护下凸壳然后二分斜率。
#include<bits/stdc++.h> using namespace std; #define int long long const int N=2e5+10,M=1010; int a[N],tag1[M],tag2[M],n,B; struct node{int x,y;}; vector<node>stk[M];int len[M]; int cross(node n1,node n2,node n3){return (n2.x-n1.x)*(n3.y-n1.y)-(n2.y-n1.y)*(n3.x-n1.x);} void pushup(int x) { len[x]=0;int bl=(x-1)*B+1,br=min(n,x*B); for(int i=bl;i<=br;i++) { while(len[x]>1&&cross(stk[x][len[x]-1],stk[x][len[x]],{i,a[i]})<=0)len[x]--; stk[x][++len[x]]={i,a[i]}; } } void upd(int l,int r,int b,int c) { int bl=(l-1)/B+1,br=(r-1)/B+1; if(bl==br) { for(int i=l;i<=r;i++)a[i]=a[i]+b*(i-1)+c; pushup(bl); } else { for(int i=l;i<=bl*B;i++)a[i]=a[i]+b*(i-1)+c; pushup(bl); for(int i=(br-1)*B+1;i<=r;i++)a[i]=a[i]+b*(i-1)+c; pushup(br); for(int i=bl+1;i<br;i++)tag1[i]+=b,tag2[i]+=c; } } int query(int l,int r) { int bl=(l-1)/B+1,br=(r-1)/B+1,ans=1e18; if(bl==br) { for(int i=l;i<=r;i++) ans=min(ans,a[i]+tag1[bl]*(i-1)+tag2[bl]); } else { for(int i=l;i<=bl*B;i++) ans=min(ans,a[i]+tag1[bl]*(i-1)+tag2[bl]); for(int i=(br-1)*B+1;i<=r;i++) ans=min(ans,a[i]+tag1[br]*(i-1)+tag2[br]); for(int i=bl+1;i<br;i++) { int l=1,r=len[i],res=1; while(l<=r) { int mid=(l+r)>>1; if(mid==1||(stk[i][mid].x-stk[i][mid-1].x)*tag1[i]<stk[i][mid-1].y-stk[i][mid].y) l=mid+1,res=mid; else r=mid-1; } int idx=stk[i][res].x; ans=min(ans,a[idx]+tag1[i]*(idx-1)+tag2[i]); } } return ans; } signed main() { cin>>n;B=sqrt(n);int q;cin>>q; for(int i=1;i<=(n-1)/B+1;i++)stk[i].resize(B+10); for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=(n-1)/B+1;i++)pushup(i); while(q--) { int op,l,r,b,c;cin>>op>>l>>r;l++; if(op==0) { cin>>b>>c; upd(l,r,b,c); } else cout<<query(l,r)<<'\n'; } return 0; }
- 1
信息
- ID
- 8138
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 11
- 已通过
- 2
- 上传者