【BZOJ4355】Play with sequence 线段树
【BZOJ4355】Play with sequence
Description
维护一个长度为N的序列a,现在有三种操作:
1)给出参数U,V,C,将a[U],a[U+1],...,a[V-1],a[V]都赋值为C。
2)给出参数U,V,C,对于区间[U,V]里的每个数i,将a[i]赋值为max(a[i]+C,0)。
3)给出参数U,V,输出a[U],a[U+1],...,a[V-1],a[V]里值为0的数字个数。
Input
第一行包含两个正整数N,M(1<=N,M<=300000),分别表示序列长度和操作个数。
第二行包含N个整数,其中第i个数表示a[i](0<=a[i]<=10^9),描述序列的初始状态。
接下来M行描述M个操作,保证1<=U<=V<=N,对于操作1,0<=C<=10^9,对于操作2,|C|<=10^9。
Output
输出若干行,每行一个整数,依次回答每个操作3的问题。
Sample Input
5 3
6 4 6 6 4
2 1 5 -5
1 3 4 4
3 1 5
6 4 6 6 4
2 1 5 -5
1 3 4 4
3 1 5
Sample Output
2
题解:懒了直接粘题解+证明。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <utility> #define lson x<<1 #define rson x<<1|1 #define mp(A,B) make_pair(A,B) #define F first #define S second using namespace std; const int maxn=300010; typedef long long ll; typedef pair<ll,int> pli; const ll NON=123456789123456ll; ll n1[maxn<<2],n2[maxn<<2],ts[maxn<<2],tc[maxn<<2],tn[maxn<<2]; int cnt[maxn<<2]; ll v[maxn]; int n,m; inline void add(int x,int l,int r,ll v) { n1[x]+=v,n2[x]+=v; if(tc[x]!=NON) tc[x]+=v; else ts[x]+=v; if(tn[x]!=NON) tn[x]+=v; } inline void cov(int x,int l,int r,ll v) { n1[x]=v,n2[x]=NON,cnt[x]=r-l+1,ts[x]=0,tc[x]=v,tn[x]=NON; } inline void con(int x,int l,int r,ll v) { if(n1[x]<v) n1[x]=v; if(tn[x]==NON||tn[x]<v) tn[x]=v; } inline void pushup(int x) { if(n1[lson]==n1[rson]) n1[x]=n1[lson],n2[x]=min(n2[lson],n2[rson]); else if(n1[lson]<n1[rson]) n1[x]=n1[lson],n2[x]=min(n2[lson],n1[rson]); else n1[x]=n1[rson],n2[x]=min(n1[lson],n2[rson]); cnt[x]=0; if(n1[x]==n1[lson]) cnt[x]+=cnt[lson]; if(n1[x]==n1[rson]) cnt[x]+=cnt[rson]; } inline void pushdown(int l,int r,int x) { int mid=(l+r)>>1; if(ts[x]) add(lson,l,mid,ts[x]),add(rson,mid+1,r,ts[x]),ts[x]=0; if(tc[x]!=NON) cov(lson,l,mid,tc[x]),cov(rson,mid+1,r,tc[x]),tc[x]=NON; if(tn[x]!=NON) con(lson,l,mid,tn[x]),con(rson,mid+1,r,tn[x]),tn[x]=NON; } void upadd(int l,int r,int x,int a,int b,ll v) { if(a<=l&&r<=b) { add(x,l,r,v); return ; } pushdown(l,r,x); int mid=(l+r)>>1; if(a<=mid) upadd(l,mid,lson,a,b,v); if(b>mid) upadd(mid+1,r,rson,a,b,v); pushup(x); } void upcov(int l,int r,int x,int a,int b,ll v) { if(a<=l&&r<=b) { cov(x,l,r,v); return ; } pushdown(l,r,x); int mid=(l+r)>>1; if(a<=mid) upcov(l,mid,lson,a,b,v); if(b>mid) upcov(mid+1,r,rson,a,b,v); pushup(x); } void upcon(int l,int r,int x,int a,int b,ll v) { if(a<=l&&r<=b) { if(v<=n1[x]) return ; if(v<n2[x]) { con(x,l,r,v); return ; } } pushdown(l,r,x); int mid=(l+r)>>1; if(a<=mid) upcon(l,mid,lson,a,b,v); if(b>mid) upcon(mid+1,r,rson,a,b,v); pushup(x); } pli query(int l,int r,int x,int a,int b) { if(a<=l&&r<=b) return mp(n1[x],cnt[x]); pushdown(l,r,x); int mid=(l+r)>>1; if(b<=mid) return query(l,mid,lson,a,b); if(a>mid) return query(mid+1,r,rson,a,b); pli sl=query(l,mid,lson,a,b),sr=query(mid+1,r,rson,a,b),ret; if(sl.F==sr.F) ret.F=sl.F,ret.S=sl.S+sr.S; else if(sl.F<sr.F) ret=sl; else ret=sr; return ret; } void build(int l,int r,int x) { tc[x]=tn[x]=NON; if(l==r) { n1[x]=v[l],n2[x]=NON,cnt[x]=1; return ; } int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); pushup(x); } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar(); return ret*f; } int main() { n=rd(),m=rd(); int i,a,b,c,op; for(i=1;i<=n;i++) v[i]=rd(); build(1,n,1); for(i=1;i<=m;i++) { op=rd(),a=rd(),b=rd(); if(op==1) c=rd(),upcov(1,n,1,a,b,c); if(op==2) c=rd(),upadd(1,n,1,a,b,c),upcon(1,n,1,a,b,0); if(op==3) { pli tmp=query(1,n,1,a,b); if(tmp.F) puts("0"); else printf("%d\n",query(1,n,1,a,b).S); } } return 0; }//4 3 9 5 7 4 1 3 3 2 2 1 3 -7 3 2 4
| 欢迎来原网站坐坐! >原文链接<