CodeForces 799C Fountains(树状数组)

树状数组
把满二叉树的形状稍微改变一下,变成下面的图形。
CodeForces 799C Fountains(树状数组)_第1张图片
用C[i]代表子树的叶子结点的权值之和。以求和举例
1=(001) C[1]=A[1];
2=(010) C[2]=A[1]+A[2];
3=(011) C[3]=A[3];
4=(100) C[4]=A[1]+A[2]+A[3]+A[4];
5=(101) C[5]=A[5];
6=(110) C[6]=A[5]+A[6];
7=(111) C[7]=A[7];
8=(1000) C[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8];
C[i]=A[i-2^k +1]+A[i-2^k+2]+…A[i]; (2^k表示从低位开始第一个1所表示的值)
有点类似于二分思想,低位k个0, 那么它的管辖范围为2的k次方个位置

//用lowbit函数实现2^k:
int lowbit(int x)
{
	return x&(-x);
}

区间查询
利用tree[i] (也就是C[i])数组,求A数组中前i项的和

int get_sum(int k)
{
	int ans=0;
	while (k)
	{
		ans+=tree[k];
		k-=k&(-k);//等价于k-=lowbit(k),实际上就是把k的二进制最后一个1变成0
	} 
	return ans;
} 

单点更新
修改A[]数组中的某一个值时 更新C[]数组

void add(int k, int num)//num为k的位置要加上的数
{
	while (k<=n)//n为a数组最大的下标 
	{
		tree[k]+=num;
		k+=k&(-k);//等价于k+=lowbit(k),实际上就是把k的二进制的1向高位推一位
	}
}

题目
Arkady plays Gardenscapes a lot. Arkady wants to build two new fountains. There are n available fountains, for each fountain its beauty and cost are known. There are two types of money in the game: coins and diamonds, so each fountain cost can be either in coins or diamonds. No money changes between the types are allowed.
Help Arkady to find two fountains with maximum total beauty so that he can buy both at the same time.

Input
The first line contains three integers n, c and d (2 ≤ n ≤ 100 000, 0 ≤ c, d ≤ 100 000) — the number of fountains, the number of coins and diamonds Arkady has.
The next n lines describe fountains. Each of these lines contain two integers bi and pi (1 ≤ bi, pi ≤ 100 000) — the beauty and the cost of the i-th fountain, and then a letter “C” or “D”, describing in which type of money is the cost of fountain i: in coins or in diamonds, respectively.

Output
Print the maximum total beauty of exactly two fountains Arkady can build. If he can’t build two fountains, print 0.

//这个树状数组中只存储买第一个井的情况,
//之后的情况会对前面进行覆盖 
#include 
#include 
#include 
#include 
using namespace std;
//C[i], D[i]表示i价值的硬币或者钻石能买的漂亮值 
int C[100005], D[100005];
int n, c, d;
void add(int tree[], int k, int num){//把k位置的漂亮值存入并更新 
	while (k<=100005){//coin或diamond的最大值 
		tree[k] = max(tree[k], num);//把num和可能影响的位置进行比较
		k += k&(-k);
	}
}
int read(int tree[], int k){
	int res = 0;
	while (k){
		res = max(tree[k], res);//把num和可能影响的位置进行比较
		k -= k&(-k);
	}
	return res;
}
int main(){
	scanf("%d%d%d", &n, &c, &d);
	memset(C, 0, sizeof(C));
	memset(D, 0, sizeof(D));
	int ans = 0;
	for (int i=1; i<=n; i++){
		int tmax=0, b, p;
		char s[5];
		scanf("%d%d%s", &b, &p, s);
		if (s[0]=='C'){
			if (p>c)
				continue;
			tmax=read(D, d);//把num和可能影响的位置进行比较
			tmax = max(tmax, read(C, c-p));//类似于背包问题 
			add(C, p, b);//更新树状数组 
			if (tmax!=0)
				ans = max(ans, tmax+b);
		}else{
			if (p>d)
				continue;
			tmax=read(C, c);
			tmax = max(tmax, read(D, d-p));
			add(D, p, b);
			if (tmax!=0)
				ans = max(ans, tmax+b);
		}
	}
	printf("%d\n", ans);
	return 0;
} 

你可能感兴趣的:(数据结构)