F - Fundraising Gym - 101889F

题目:

题目链接:传送门

题目意思:给你n个人,每个人有两个值和一个贡献,让你选择一些人使贡献最大,规则是任意两个人,一个人的两个值都要大于另一个人的两个值。

思路:很像今年ccpc网络赛的一道题目,简直就是一毛一样。(当时队伍没做出来)。。看了题解后........

相当于给你一个二维坐标,我们只要将它先离散成连续的几个点,然后用树状数组维护y轴的最大值就行了。

附上代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-6;
const int N = 1e5 + 5;
#define ll long long
struct inst {
	int x;
	int y;
	long long val;
};
struct inst ax[N];
int cmp(struct inst a, struct inst b) {
	if (a.x == b.x) {
		return a.y < b.y;
	}
	else return a.x < b.x;
}
int X[N], Y[N];
int n;
long long c[N], a[N];	
int lowbit(int x)
{
	return (x)&(-x);
}
void update_onepos(int pos, long long x)
{
	while (pos <= n)
	{
		c[pos] = max(c[pos], x);
		pos += lowbit(pos);
	}
}
long long query(int pos)		
{
	long long  sum = 0;
	while (pos > 0) {
		sum =max(sum,c[pos]);
		pos -= lowbit(pos);
	}
	return sum;
}
vector<inst>q;
int main(void) {
	scanf("%d", &n);
	q.clear();
	for (int i = 0; i < n; i++) {
		scanf("%d%d%lld", &ax[i].x, &ax[i].y, &ax[i].val);
		X[i] = ax[i].x;
		Y[i] = ax[i].y;
	}
	sort(X, X + n);
	sort(Y, Y + n);
	int tot1 = unique(X, X + n) - X;
	int tot2 = unique(Y, Y + n) - Y;
	for (int i = 0; i < n; i++) {
		ax[i].x = lower_bound(X, X + tot1, ax[i].x) - X+1;
		ax[i].y = lower_bound(Y, Y + tot2, ax[i].y) - Y+1;
	}
	long long maxx = 0;
	sort(ax, ax + n, cmp);
	for (int i = 0; i < n; i++) {
		if (i >= 1 && ax[i].x != ax[i - 1].x) {
			for (int z = 0; z < q.size(); z++) {
				update_onepos(q[z].y, q[z].val);
			}
			q.clear();
		}
		if (i != n - 1) {
			if (ax[i].x == ax[i + 1].x&&ax[i].y == ax[i + 1].y) {
				ax[i + 1].val += ax[i].val;
				continue;
			}
		}
		long long ans = query(ax[i].y - 1) + ax[i].val;
		ax[i].val = ans;
		q.push_back(ax[i]);
		maxx = max(maxx, ans);
	}
	printf("%lld\n", maxx);
	return 0; 
}

猜你喜欢

转载自blog.csdn.net/liexss/article/details/83018699