分块涛开始了他的分块,据说这是他第一次写重构,于是喜闻乐见T掉了。优化到最后极限数据还是要跑70s,常数需要再优化30倍。。。最后半小时发现b是一个1到n的排列。。。然后并不知道有什么用。于是15分钟后没过一题,挂机4小时45分钟,虽然qt成功get成就在多校中拿一血可以吹一年,不过我们还是太菜了。
1-n的排列,那么每个元素最多加q次,那么答案最大是q+q/2+q/3...q/n约等于qlnq,于是我们把线段树的每个地方的元素赋成-b[i],然后维护最大值,一旦有等于0的元素,说明这个地方要+1了,吧这个地方变成b[i],再用树状数组在i这个地方+1,每次add操作后都要判断这一段区间有没有最大值=0,有的话就一直取出来,然后那个地方-b[i],直到没有位置=0,最多进行qlnq次,复杂度就是qlnqlogn
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxl 100010
using namespace std;
int n,m;
int a[maxl];
long long b[maxl];
typedef pair<int,int> p;
struct node
{
int l,r,tag;p mx;
}tree[maxl<<2];
char ch[22];
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;tree[k].tag=0;
if(l==r)
{
tree[k].mx=make_pair(-a[l],l);
tree[k].tag=0;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
}
inline void prework()
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
}
inline void gank(int k)
{
if(tree[k].l!=tree[k].r)
{
tree[k<<1].mx.first+=tree[k].tag;
tree[k<<1].tag+=tree[k].tag;
tree[k<<1|1].mx.first+=tree[k].tag;
tree[k<<1|1].tag+=tree[k].tag;
}
tree[k].tag=0;
}
inline void add(int k,int l,int r,int x)
{
if(tree[k].l==l && tree[k].r==r)
{
tree[k].mx.first+=x;
tree[k].tag+=x;
return;
}
if(tree[k].tag)
gank(k);
int mid=(tree[k].l+tree[k].r)>>1;
if(r<=mid)
add(k<<1,l,r,x);
else
if(l>mid)
add(k<<1|1,l,r,x);
else
add(k<<1,l,mid,x),add(k<<1|1,mid+1,r,x);
tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
}
inline p getmax(int k,int l,int r)
{
p mx;
if(tree[k].tag)
gank(k);
if(tree[k].l==l && tree[k].r==r)
return tree[k].mx;
int mid=(tree[k].l+tree[k].r)>>1;
if(r<=mid)
mx=getmax(k<<1,l,r);
else
if(l>mid)
mx=getmax(k<<1|1,l,r);
else
mx=max(getmax(k<<1,l,mid),getmax(k<<1|1,mid+1,r));
tree[k].mx=max(tree[k<<1].mx,tree[k<<1|1].mx);
return mx;
}
inline void badd(int i,long long x)
{
if(!i) return;
while(i<=n)
{
b[i]+=x;
i+=i&-i;
}
}
inline long long sum(int i)
{
long long s=0;
while(i)
{
s+=b[i];
i-=i&-i;
}
return s;
}
inline void mainwork()
{
int l,r;
memset(b,0,sizeof(b));
for(int i=1;i<=m;i++)
{
scanf("%s%d%d",ch,&l,&r);
if(ch[0]=='a')
{
add(1,l,r,1);
p d=getmax(1,l,r);
while(d.first>=0)
{
badd(d.second,1);
add(1,d.second,d.second,-a[d.second]);
d=getmax(1,l,r);
}
}
else
printf("%lld\n",sum(r)-sum(l-1));
}
}
int main()
{
// freopen("1007.in","r",stdin);
// freopen("std.out","w",stdout);
while(~scanf("%d%d",&n,&m))
{
prework();
mainwork();
//print();
}
return 0;
}