HDU6315 Naive Operations
阿新 • • 發佈:2018-11-07
看到大佬的部落格我才做出來這道題,轉載一波
轉載地址:https://blog.csdn.net/fire_to_cheat_/article/details/81252648
/*hdu 1007 首先我們在建立線段樹之前應該思考的是線段樹的節點維護一個什麼值, 在比賽過程中,我想到了維護a[i]的值但是時間複雜度太高,又想到維護a[i]/b[i]但是取下整, 這樣的話無法更新∑的值。 在題解中,維護了b[i]的值,因為a[i]最初是0,所以在update過程中當a[i]>=b[i]時,a[i]/b[i]才>=1; 才會對sum有貢獻,所以不妨維護b[i]的值,對每次區間更新,將區間中的b[i]減1,當b[i]減到0時,更新sum的值+1,然後b[i]更新回初始的b[i]的值 整個更新過程中需要維護lazy標誌、numzero當前子樹中0的個數(即sum+1的次數)、minx當前子樹中最小的b[i]值、valb當前節點初始的b[i]值 lazy是a陣列向下推的標誌,就是加的次數,其實就是b要減的數 */ #include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int MAXN=201000; struct { int minx,valb,numzero; int lazy; }sum[MAXN<<2]; int b[MAXN]; void push_up(int rt) { sum[rt].numzero=sum[rt<<1].numzero+sum[rt<<1|1].numzero; sum[rt].minx=min(sum[rt<<1].minx,sum[rt<<1|1].minx); } void push_down(int rt,int l,int r) { sum[rt<<1].lazy+=sum[rt].lazy; sum[rt<<1|1].lazy+=sum[rt].lazy; sum[rt<<1].minx-=sum[rt].lazy; sum[rt<<1|1].minx-=sum[rt].lazy; sum[rt].lazy=0; } void build(int l,int r,int rt=1) { sum[rt].lazy=0; sum[rt].numzero=0; if(l==r) { sum[rt].lazy=0; sum[rt].minx=b[l]; sum[rt].numzero=0; sum[rt].valb=b[l]; return; } int m=(l+r)>>1; build(lson); build(rson); push_up(rt); } /*update操作 */ void update(int L,int R,int l,int r,int rt=1) { if(L<=l&&r<=R&&sum[rt].minx>1) { sum[rt].lazy++; sum[rt].minx--; return; } if(l==r&&sum[rt].minx==1) { sum[rt].numzero++; sum[rt].lazy=0; sum[rt].minx=sum[rt].valb; return; } if(sum[rt].lazy>0) push_down(rt,l,r); int m=(l+r)>>1; if(L<=m)update(L,R,lson); if(m<R)update(L,R,rson); push_up(rt); } /*query操作 求和操作,就是求子樹中numzero和 */ int query(int L,int R,int l,int r,int rt=1) { if(L<=l&&r<=R) { return sum[rt].numzero; } if(sum[rt].lazy>0)push_down(rt,l,r); int m=(l+r)>>1; int ret=0; if(L<=m)ret+=query(L,R,lson); if(R>m)ret+=query(L,R,rson); return ret; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int n,m; while(cin>>n>>m) { memset(b,0,sizeof(b)); char ch[10]; int L,R; for(int i=1;i<=n;i++) scanf("%d",b+i); build(1,n,1); while(m--) { scanf("%s",ch); scanf("%d%d",&L,&R); if(ch[0]=='a') { update(L,R,1,n,1); } else if(ch[0]=='q') { printf("%d\n",query(L,R,1,n,1)); } } } return 0; }