题目:
题目链接:传送门
题目意思:给你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;
}