题意略。
思路:本题的思路总的来说就是暴力 + 剪枝。
我们依然用线段树来维护:
定义结点node{ l , r , minn , contirbute} 分别为某个区间的左右端点,和该区间(b序列)内的最小值与该区间对答案的贡献。
当我们修改到某一个区间的时候,如果该区间的minn > 1,那么minn--,并且给该区间打上懒标记。
如果该区间的minn == 1,那么我们看一下这个区间的左右两个子区间,对于minn > 1的子区间,我们就采取上面的操作。
对于minn == 1的子区间,我们就一直往下找,直到定位到了最底层的叶子节点,对于该子节点的minn,我们将它复原,但是把它的contribute += 1。
其实就是利用minn值来剪枝。
详见代码:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; struct node{ int l,r,minn,contri; node(int a = 0,int b = 0,int c = 0,int d = 0){ l = a,r = b,minn = c,contri = d; } }; node store[maxn<<2]; int depot[maxn],add[maxn<<2],n,q; char op[10]; void pushup(int id){ store[id].contri = store[id<<1].contri + store[id<<1 | 1].contri; store[id].minn = min(store[id<<1].minn,store[id<<1 | 1].minn); } void pushdown(int id){ if(add[id]){ store[id<<1].minn -= add[id]; store[id<<1 | 1].minn -= add[id]; add[id<<1] += add[id]; add[id<<1 | 1] += add[id]; add[id] = 0; } } void build(int l,int r,int id){ store[id].l = l,store[id].r = r; if(l == r){ store[id].minn = depot[l]; store[id].contri = 0; return; } int mid = (l + r)>>1; build(l,mid,id<<1); build(mid + 1,r,id<<1 | 1); pushup(id); } void modify(int l,int r,int id){ if(store[id].l == l && store[id].r == r && store[id].minn > 1){ store[id].minn -= 1; add[id] += 1; return; } if(store[id].l == store[id].r){ store[id].minn -= 1; add[id] += 1; if(store[id].minn <= 0){ store[id].minn = depot[l]; store[id].contri += 1; } return; } pushdown(id); int mid = (store[id].l + store[id].r)>>1; if(r <= mid) modify(l,r,id<<1); else if(mid < l) modify(l,r,id<<1 | 1); else{ modify(l,mid,id<<1); modify(mid + 1,r,id<<1 | 1); } pushup(id); } int query(int l,int r,int id){ if(store[id].l == l && store[id].r == r){ return store[id].contri; } pushdown(id); int mid = (store[id].l + store[id].r)>>1; int ret = 0; if(r <= mid) ret = query(l,r,id<<1); else if(mid < l) ret = query(l,r,id<<1 | 1); else ret = query(l,mid,id<<1) + query(mid + 1,r,id<<1 | 1); pushup(id); return ret; } int main(){ while(scanf("%d%d",&n,&q) == 2){ memset(add,0,sizeof(add)); for(int i = 1;i <= n;++i){ scanf("%d",&depot[i]); } build(1,n,1); for(int i = 0;i < q;++i){ int l,r; scanf("%s%d%d",op,&l,&r); if(op[0] == 'a'){ modify(l,r,1); } else{ int ans = query(l,r,1); printf("%d ",ans); } } } return 0; }