题目:Naive Operations
题意:
给定一个b数组,a数组初始均为0。有2种操作:add l r:把a[l...r]均+1; query l r:求 .
floor()为向下取整。
思路:
本题总体思路是O(n)暴力更新到每一个叶子节点,然后O(logn)查询。但这样会T,需要一个减枝。我们维护区间a的最大值和b的最小值,如果更新后一个区间内最大的a都小于b,那么必然不会使查询时的答案有所改变。这种情况下,我们使用lazy标记,就不需要更新到每一个叶子节点了。其余情况下,不能保证更新后是否会对答案有所影响,所以需要更新到每一个叶子节点,当叶子节点a的值>=b的值时,让那一点的sum++,并使b+=它原来输入的值。
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX = 100000+100;
typedef struct{
int maxa,minb; //维护区间a的最大值和b的最小值
int lazy;
ll sum; //维护区间的答案个数
}STree;
int n,q;
int b[MAX];
STree tree[MAX<<2];
void pushup(int root)
{
tree[root].maxa=max(tree[root<<1].maxa,tree[root<<1|1].maxa);
tree[root].minb=min(tree[root<<1].minb,tree[root<<1|1].minb);
tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum;
}
void pushdown(int root)
{
if(tree[root].lazy)
{
tree[root<<1].maxa+=tree[root].lazy;
tree[root<<1|1].maxa+=tree[root].lazy;
tree[root<<1].lazy+=tree[root].lazy;
tree[root<<1|1].lazy+=tree[root].lazy;
tree[root].lazy=0;
}
}
void build(int l,int r,int root)
{
tree[root].lazy=0;
if(l==r)
{
tree[root].maxa=0;
tree[root].minb=b[l];
tree[root].sum=0;
return;
}
int mid=(l+r)>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
pushup(root);
}
void update(int l,int r,int L,int R,int root)
{
if(l<=L&&R<=r)
{
tree[root].maxa++;
if(tree[root].maxa<tree[root].minb)
{
tree[root].lazy++;
return;
}
if(L==R&&tree[root].maxa>=tree[root].minb)
{
tree[root].sum++;
tree[root].minb+=b[L];
return;
}
}
pushdown(root);
int mid=(L+R)>>1;
if(l<=mid)
update(l,r,L,mid,root<<1);
if(mid<r)
update(l,r,mid+1,R,root<<1|1);
pushup(root);
}
ll query(int l,int r,int L,int R,int root)
{
if(l<=L&&R<=r)
{
return tree[root].sum;
}
pushdown(root);
int mid=(L+R)>>1;
ll ans=0;
if(l<=mid)
ans+=query(l,r,L,mid,root<<1);
if(mid<r)
ans+=query(l,r,mid+1,R,root<<1|1);
return ans;
}
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
}
build(1,n,1);
while(q--)
{
char str[20];
int l,r;
scanf("%s%d%d",str,&l,&r);
if(str[0]=='a')
{
update(l,r,1,n,1);
}
else if(str[0]=='q')
{
ll ans=query(l,r,1,n,1);
printf("%lld\n",ans);
}
}
}
return 0;
}