题意:
给出长度为n的b序列,b序列为1~n的一个排列,a序列初始为全0。
给出q次操作,add操作使a[l,r]+1,query操作求[l,r]的ai/bi的和。
思路:
对于一个ai/bi,只有当ai增加到bi时才有1个贡献,所以用线段树维护一个c数组,记录ai离下一次做出贡献还差多少次add。
当[l,r]中的min(c)==1时,把标记下推,当标记到达叶子节点是贡献+1。
因为b是1~n的排列,所以最多更新nlogn次,每次操作复杂度为logn,总体复杂度O(nlog^2n)
代码:
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <map>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <sstream>
#define pb push_back
#define X first
#define Y second
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pii pair<int,int>
#define qclear(a) while(!a.empty())a.pop();
#define lowbit(x) (x&-x)
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define mst(a,b) memset(a,b,sizeof(a))
#define cout3(x,y,z) cout<<x<<" "<<y<<" "<<z<<endl
#define cout2(x,y) cout<<x<<" "<<y<<endl
#define cout1(x) cout<<x<<endl
#define IOS std::ios::sync_with_stdio(false)
#define SRAND srand((unsigned int)(time(0)))
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
using namespace std;
const double PI=acos(-1.0);
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=100005;
const int maxm=10005;
struct node {
int mn,div,ans,lazy;
};
node st[maxn<<2];
int b[maxn];
void pushdown(int o) {
st[o<<1].lazy+=st[o].lazy;
st[(o<<1)|1].lazy+=st[o].lazy;
st[o<<1].mn-=st[o].lazy;
st[(o<<1)|1].mn-=st[o].lazy;
st[o].lazy=0;
}
void pushup(int o) {
st[o].ans=st[o<<1].ans+st[(o<<1)|1].ans;
st[o].mn=min(st[o<<1].mn,st[(o<<1)|1].mn);
}
void build(int o,int l,int r) {
st[o].lazy=st[o].ans=0;
if(l==r) {
st[o].div=st[o].mn=b[l];
st[o].ans=0;
return ;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);
build((o<<1)|1,mid+1,r);
st[o].mn=min(st[o<<1].mn,st[(o<<1)|1].mn);
}
void update(int o,int l,int r,int ql,int qr) {
if (l > r) return;
if(l==ql&&r==qr&&st[o].mn>1) {
st[o].lazy++;
st[o].mn--;
return ;
}
if(l==r&&st[o].mn==1) {
st[o].mn=st[o].div;
st[o].ans++;
st[o].lazy=0;
return ;
}
if(st[o].lazy>0)
pushdown(o);
int mid=(l+r)>>1;
if(qr<=mid) {
update(o<<1,l,mid,ql,qr);
} else if(ql>mid) {
update((o<<1)|1,mid+1,r,ql,qr);
} else {
update(o<<1,l,mid,ql,mid);
update((o<<1)|1,mid+1,r,mid+1,qr);
}
pushup(o);
}
int query(int o,int l,int r,int ql,int qr) {
if (l > r) return 0;
if(ql<=l&&r<=qr) {
return st[o].ans;
}
int mid=(l+r)>>1;
if(qr<=mid) {
return query(o<<1,l,mid,ql,qr);
} else if(ql>mid) {
return query((o<<1)|1,mid+1,r,ql,qr);
} else {
return query(o<<1,l,mid,ql,qr)+query((o<<1)|1,mid+1,r,ql,qr);
}
}
void solve() {
int n,q;
while(~sdd(n,q)) {
for(int i=1; i<=n; i++) {
sd(b[i]);
}
build(1,1,n);
while(q--) {
char op[20];
scanf("%s",op);
int l,r;
sdd(l,r);
if(op[0]=='a') {
update(1,1,n,l,r);
} else {
int ans=query(1,1,n,l,r);
printf("%d\n",ans);
}
}
}
return ;
}
int main() {
#ifdef LOCAL
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#else
// freopen("","r",stdin);
// freopen("","w",stdout);
#endif
solve();
return 0;
}