BZOJ 4355: Play with sequence
调了好久,还是黑盒测试有前途
我以前怕不是学了假的吉利线段树(我第一次知道还要记次小值去更新的........)
#include<cstdio> #include<algorithm> #define ll long long using namespace std; int n,m,tr_sz[1500005],a[300005]; ll tag_cov[1500005],tr_min[1500005],tag_add[1500005],tr_sc[1500005]; void update_cov(int t,ll c,int l,int r){ tag_add[t]=0; tag_cov[t]=tr_min[t]=c,tr_sc[t]=1ll<<60; //if (t==8) printf("%d %d\n",l,r); tr_sz[t]=r-l+1; } void update_add(int t,ll c){ tag_add[t]+=c; tr_min[t]+=c; if (tr_sc[t]!=1ll<<60) tr_sc[t]+=c; } void update(int t,int l,int r){ ll Min=min(tr_min[t<<1],tr_min[t<<1|1]); tr_min[t]=Min; tr_sz[t]=(tr_min[t<<1]==Min?tr_sz[t<<1]:0)+(tr_min[t<<1|1]==Min?tr_sz[t<<1|1]:0); tr_sc[t]=min(tr_min[t<<1]==Min?tr_sc[t<<1]:tr_min[t<<1],tr_min[t<<1|1]==Min?tr_sc[t<<1|1]:tr_min[t<<1|1]); if (tr_sz[t]>r-l+1) printf("!!!\n"); } void update_min(int t,ll c){ tr_min[t]=max(tr_min[t],c); } void push_down(int t,int l,int r){ int mid=(l+r)>>1; if (tag_cov[t]!=-1) update_cov(t<<1,tag_cov[t],l,mid),update_cov(t<<1|1,tag_cov[t],mid+1,r); if (tag_add[t]) update_add(t<<1,tag_add[t]),update_add(t<<1|1,tag_add[t]); update_min(t<<1,tr_min[t]),update_min(t<<1|1,tr_min[t]); tag_cov[t]=-1,tag_add[t]=0; } void build(int t,int l,int r){ tag_cov[t]=-1,tag_add[t]=0; if (l==r){ tr_min[t]=a[l],tr_sc[t]=1ll<<60,tr_sz[t]=1; return; } int mid=(l+r)>>1; build(t<<1,l,mid); build(t<<1|1,mid+1,r); update(t,l,r); } void modify_cov(int t,int l,int r,int x,int y,ll c){ if (r<x || l>y) return; if (l>=x && r<=y){ update_cov(t,c,l,r); return; } push_down(t,l,r); int mid=(l+r)>>1; modify_cov(t<<1,l,mid,x,y,c); modify_cov(t<<1|1,mid+1,r,x,y,c); update(t,l,r); } void modify_add(int t,int l,int r,int x,int y,ll c){ if (r<x || l>y) return ; if (l>=x && r<=y){ update_add(t,c); return; } push_down(t,l,r); int mid=(l+r)>>1; modify_add(t<<1,l,mid,x,y,c); modify_add(t<<1|1,mid+1,r,x,y,c); update(t,l,r); } void modify_0(int t,int l,int r,int x,int y){ if (r<x || l>y) return; if (tr_min[t]>=0) return; if (l>=x && r<=y && tr_sc[t]>0){ update_min(t,0); return; } push_down(t,l,r); int mid=(l+r)>>1; modify_0(t<<1,l,mid,x,y); modify_0(t<<1|1,mid+1,r,x,y); update(t,l,r); } int query(int t,int l,int r,int x,int y){ if (r<x || l>y) return 0; if (tr_min[t]) return 0; if (l>=x && r<=y) { //printf("%d %d %d %d\n",l,r,tr_sz[t],t); return tr_sz[t]; } push_down(t,l,r); int mid=(l+r)>>1; return query(t<<1,l,mid,x,y)+query(t<<1|1,mid+1,r,x,y); } int main(){ scanf("%d%d",&n,&m); for (int i=1; i<=n; i++) scanf("%d",&a[i]); build(1,1,n); while (m--){ int cas,l,r,c; scanf("%d%d%d",&cas,&l,&r); if (cas==1 || cas==2) scanf("%d",&c); if (cas==1) modify_cov(1,1,n,l,r,c); if (cas==2) modify_add(1,1,n,l,r,c),modify_0(1,1,n,l,r); if (cas==3) printf("%d\n",query(1,1,n,l,r)); } return 0; }