留了几天的坑终于填了。。。
这个东西是线段树取区间最值问题。。。在吉司机16的论文里面。。。
其实就是让修改值和区间次大比较,假如次大较小就可以只改最大值,维护一下就可以了
注意到标记大小是按深度递增递增的
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct node { LL mx,mxc,sx,sum,md; }tr[2100000];int trlen,a[1100000]; void update(int now) { int lc=now<<1,rc=now<<1|1; tr[now].sum=tr[lc].sum+tr[rc].sum; tr[now].mx=max(tr[lc].mx,tr[rc].mx); tr[now].mxc=0; if(tr[lc].mx==tr[now].mx)tr[now].mxc+=tr[lc].mxc; if(tr[rc].mx==tr[now].mx)tr[now].mxc+=tr[rc].mxc; tr[now].sx=max(tr[lc].sx,tr[rc].sx); if(tr[lc].mx!=tr[rc].mx) tr[now].sx=max(tr[now].sx,min(tr[lc].mx,tr[rc].mx)); } void pushdown(int now) { if(tr[now].md!=0) { int lc=now<<1,rc=now<<1|1; if(tr[lc].mx>tr[now].md) { tr[lc].sum-=tr[lc].mxc*(tr[lc].mx-tr[now].mx); tr[lc].mx=tr[lc].md=tr[now].md; } if(tr[rc].mx>tr[now].md) { tr[rc].sum-=tr[rc].mxc*(tr[rc].mx-tr[now].mx); tr[rc].mx=tr[rc].md=tr[now].md; } } } //~~~~~~~~~~~~~~tool~~~~~~~~~~~~~~~~~~~~~~~~~ void bt(int now,int ql,int qr) { if(ql==qr) { tr[now].mx=tr[now].sum=a[ql]; tr[now].mxc=1; tr[now].sx=-1; } else { int mid=(ql+qr)/2; int lc=now<<1,rc=now<<1|1; bt(lc,ql,mid),bt(rc,mid+1,qr); update(now); } tr[now].md=0; } void change(int now,int ql,int qr,int l,int r,LL k) { if(tr[now].mx<=k)return ; if(ql==qr){tr[now].mx=tr[now].sum=k;return ;} int mid=(ql+qr)/2; int lc=now<<1,rc=now<<1|1; if(ql==l&&qr==r) { if(tr[now].sx<k) { tr[now].sum-=tr[now].mxc*(tr[now].mx-k); tr[now].mx=tr[now].md=k; return ; } else { change(lc,ql,mid,l,mid,k),change(rc,mid+1,qr,mid+1,r,k); update(now); } } else { pushdown(now); if(r<=mid) change(lc,ql,mid,l,r,k); else if(mid+1<=l)change(rc,mid+1,qr,l,r,k); else change(lc,ql,mid,l,mid,k),change(rc,mid+1,qr,mid+1,r,k); update(now); } } //~~~~~~~~~~~~~~~~~~~~~~change~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL getmax(int now,int ql,int qr,int l,int r) { if(ql==l&&qr==r)return tr[now].mx; int mid=(ql+qr)/2; int lc=now<<1,rc=now<<1|1; pushdown(now); if(r<=mid) return getmax(lc,ql,mid,l,r); else if(mid+1<=l)return getmax(rc,mid+1,qr,l,r); else return max(getmax(lc,ql,mid,l,mid),getmax(rc,mid+1,qr,mid+1,r)); } LL getsum(int now,int ql,int qr,int l,int r) { if(ql==l&&qr==r)return tr[now].sum; int mid=(ql+qr)/2; int lc=now<<1,rc=now<<1|1; pushdown(now); if(r<=mid) return getsum(lc,ql,mid,l,r); else if(mid+1<=l)return getsum(rc,mid+1,qr,l,r); else return getsum(lc,ql,mid,l,mid)+getsum(rc,mid+1,qr,mid+1,r); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~solve~~~~~~~~~~~~~~~~~~~~~~~~~~ int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); trlen=0;bt(1,1,n); int op,x,y;LL d; while(m--) { scanf("%d",&op); if(op==0) { scanf("%d%d%lld",&x,&y,&d); change(1,1,n,x,y,d); } else { scanf("%d%d",&x,&y); if(op==1)printf("%lld\n",getmax(1,1,n,x,y)); else printf("%lld\n",getsum(1,1,n,x,y)); } } } return 0; }
原文地址:https://www.cnblogs.com/AKCqhzdy/p/10242335.html
时间: 2024-10-16 03:50:15