题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=6315
题目分析:
有两个数组a和b,a数组的初始值全部为0,题目有两种操作,更新操作将a数组的(l, r)加1,询问操作要求输出 ∑⌊ai/bi⌋(l<=i<=r),用线段树来维护a数组的最大值maxa和b数组的最小值minb,只更新maxa >= minb的区间即可,(maxa-minb)代表的是a的最大值到达b的最小值需要更新的次数,需要注意叶子结点的具体更新。
PS:
update中叶子结点的更新
tree[root].minb += b[ll];
换成下面这样就会TLE
tree[root].maxa -= b[ll];
换成第二个式子之后答案还是一致的,但是时间增加了很多,一直搞不懂为什么。
代码:
#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int MAXN = 1e5+10;
int b[MAXN];
struct Node
{
int l, r;
int minb;
int maxa;
int tmp;
int sum;
}tree[MAXN*4];
void pushdown(int root)
{
if(tree[root].tmp)
{
tree[root<<1].maxa += tree[root].tmp;
tree[root<<1|1].maxa += tree[root].tmp;
tree[root<<1].tmp += tree[root].tmp;
tree[root<<1|1].tmp += tree[root].tmp;
tree[root].tmp = 0;
}
}
void build(int l, int r, int root)
{
// cout<<l<<" "<<r<<endl;
tree[root].l = l;
tree[root].r = r;
tree[root].sum = 0;
tree[root].tmp = 0;
tree[root].maxa = 0;
if(l == r)
{
tree[root].minb = b[l];
return ;
}
int mid = (l+r)>>1;
build(l, mid, root<<1);
build(mid+1, r, root<<1|1);
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);
}
void update(int root, int l, int r)
{
int ll = tree[root].l;
int rr = tree[root].r;
//cout<<ll<<" "<<rr<<endl;
if(l <= ll && rr <= r)
{
tree[root].maxa++;
if(tree[root].maxa < tree[root].minb)
{
tree[root].tmp++;
return ;
}
if(ll == rr && tree[root].maxa >= tree[root].minb)
{
tree[root].sum++;
tree[root].minb += b[ll];
return ;
}
}
pushdown(root);
int mid = (ll + rr)>>1;
if(l <= mid)
update(root<<1, l, r);
if(r > mid)
update(root<<1|1, l, r);
tree[root].maxa = max(tree[root<<1].maxa, tree[root<<1|1].maxa);
tree[root].sum = tree[root<<1].sum + tree[root<<1|1].sum;
tree[root].minb = min(tree[root<<1].minb, tree[root<<1|1].minb);
}
int query(int root, int l, int r)
{
int ll = tree[root].l;
int rr = tree[root].r;
if(l <= ll && rr <= r)
{
return tree[root].sum;
}
pushdown(root);
int mid = (ll + rr)>>1;
int sum = 0;
if(l <= mid)
{
sum += query(root<<1, l, r);
}
if(r > mid)
{
sum += query(root<<1|1, l, r);
}
return sum;
}
int main()
{
freopen("input.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int n, q;
while(scanf("%d %d", &n, &q) != EOF)
{
for(int i = 1; i <= n; i++)
{
scanf("%d", &b[i]);
}
build(1, n, 1);
char str[10];
int l, r;
while(q--)
{
scanf("%s %d %d", str, &l, &r);
if(strcmp(str, "add") == 0)
{
update(1, l, r);
}
else
{
int ans = query(1, l, r);
cout<<ans<<endl;
}
}
}
fclose(stdin);
fclose(stdout);
return 0;
}