1 条题解
-
0
自动搬运
来自洛谷,原作者为

qwaszx
不再为往事受困.搬运于
2025-08-24 22:13:29,当前版本为作者最后更新于2020-08-28 13:59:48,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
首先,欢迎加入EI队长粉丝裙:450567214
本题的一个 做法由 EI 队长在她的集训队论文《浅谈函数最值的动态维护》中给出,其中 分别代表序列长度、修改次数、查询次数. 该数据结构被称为 Kinetic Tournament 树 (KTT).
该做法的原理在 EI's blog 或论文中有详细阐述,这里仅给出一个直接实现及可参考的代码.
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=400500; const long long INF=2e18; int n,w[N],m; long long tag[N<<2]; struct LINE//一次函数 { int k;long long b; LINE operator +(const LINE &a)const{return (LINE){k+a.k,b+a.b};} }; pair<LINE,long long> max(LINE a,LINE b)//对两个一次函数取x=0时的最值,同时给出max的选取不发生变化的最大值C(即 x>C 时max变成另一个) { if(a.k<b.k||(a.k==b.k&&a.b<b.b))swap(a,b); if(a.b>=b.b){return make_pair(a,INF);} return make_pair(b,(b.b-a.b)/(a.k-b.k)); } struct Node { LINE ls,rs,ans,sum;long long x;//增量>x时子树内会有max的选取发生变化 Node operator +(const Node &a)const { Node t;t.x=min(x,a.x); pair<LINE,long long>tmp=max(ls,sum+a.ls); t.ls=tmp.first,t.x=min(t.x,tmp.second); tmp=max(a.rs,rs+a.sum); t.rs=tmp.first,t.x=min(t.x,tmp.second); tmp=max(ans,a.ans);t.x=min(t.x,tmp.second); tmp=max(tmp.first,rs+a.ls); t.ans=tmp.first,t.x=min(t.x,tmp.second); t.sum=sum+a.sum; return t; } }a[N<<2]; void build(int rot,int lt,int rt) { if(lt==rt) { LINE t={1,w[lt]}; a[rot]=(Node){t,t,t,t,INF}; return; } int mid=(lt+rt)>>1; build(rot<<1,lt,mid),build(rot<<1|1,mid+1,rt); a[rot]=a[rot<<1]+a[rot<<1|1]; } void upd(int rot,long long w) { tag[rot]+=w;a[rot].x-=w; a[rot].ls.b+=a[rot].ls.k*w; a[rot].rs.b+=a[rot].rs.k*w; a[rot].ans.b+=a[rot].ans.k*w; a[rot].sum.b+=a[rot].sum.k*w; } void upd(int rot,int lt,int rt,long long w) { if(w>a[rot].x)//如果增量使得子树内有max发生变化则递归下去重构 { long long t=tag[rot]+w;tag[rot]=0;int mid=(lt+rt)>>1; upd(rot<<1,lt,mid,t),upd(rot<<1|1,mid+1,rt,t); a[rot]=a[rot<<1]+a[rot<<1|1]; } else upd(rot,w); } void pushdown(int rot) { if(tag[rot]) { long long t=tag[rot];tag[rot]=0; upd(rot<<1,t),upd(rot<<1|1,t); } } void update(int rot,int lt,int rt,int lq,int rq,int x) { if(lt>=lq&&rt<=rq){upd(rot,lt,rt,x);return;} pushdown(rot); int mid=(lt+rt)>>1; if(lq<=mid)update(rot<<1,lt,mid,lq,rq,x); if(rq>mid)update(rot<<1|1,mid+1,rt,lq,rq,x); a[rot]=a[rot<<1]+a[rot<<1|1]; } Node query(int rot,int lt,int rt,int lq,int rq) { if(lt>=lq&&rt<=rq)return a[rot]; pushdown(rot); int mid=(lt+rt)>>1; if(rq<=mid)return query(rot<<1,lt,mid,lq,rq); if(lq>mid)return query(rot<<1|1,mid+1,rt,lq,rq); return query(rot<<1,lt,mid,lq,mid)+query(rot<<1|1,mid+1,rt,mid+1,rq); } int getin() { int x=0,f=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')f=-1,ch=getchar(); while(ch>='0'&&ch<='9')x=x*10+ch-48,ch=getchar(); return x*f; } int main() { n=getin(),m=getin(); for(int i=1;i<=n;i++)w[i]=getin(); build(1,1,n); for(int i=1,opt,l,r,x;i<=m;i++) { opt=getin(),l=getin(),r=getin(); if(opt==1)x=getin(),update(1,1,n,l,r,x); else printf("%lld\n",max(0ll,query(1,1,n,l,r).ans.b)); } }
- 1
信息
- ID
- 4747
- 时间
- 1800ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者