HDU——6315

题目链接:

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;
}

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值