题目链接: https://ac.nowcoder.com/acm/contest/881/I
题意: 给你n个点,每个点的坐标为(xi,yi),有两个权值ai,bi。
现在要你将它分成A,B两部分,使得在满足“A的点不能落在在B的点的右下方”的条件下∑i∈Aai+∑j∈Bbj最大。
思路:可以参考一下大佬的博客
- https://www.cnblogs.com/buerdepepeqi/p/11231875.html
- https://blog.csdn.net/u013534123/article/details/96465704
- https://www.cnblogs.com/Dillonh/p/11216839.html
代码:
下午的时候,看了大佬写的博文,也按着他的思路自己敲了一遍,后面发现自己忘记开long long 就索性全文替换了,改完之后再交发现还是没过,emmmmmm(只通过0.01%的样例), 晚上突然一想到,我去,忘记初始化lazy了,哎…
#include <bits/stdc++.h>
using namespace std;
const long long MAXN = 1e5 + 5;
long long node[MAXN<<2], lazy[MAXN<<2];
inline void PushUp(long long root)
{
node[root] = max(node[root<<1], node[root<<1|1]);
}
inline void BuildTree(long long root, long long l, long long r)
{
if(l == r){
node[root] = 0;
return ;
}
//lazy 也要初始化,否则会有遗留
lazy[root] = 0;
long long mid = (l + r) >> 1;
BuildTree(root<<1, l, mid);
BuildTree(root<<1|1, mid + 1, r);
PushUp(root);
}
inline void PushDown(long long root, long long ln, long long rn)
{
if(lazy[root]){
lazy[root<<1] += lazy[root];
lazy[root<<1|1] += lazy[root];
node[root<<1] += lazy[root];
node[root<<1|1] += lazy[root];
lazy[root] = 0;
}
}
inline void Update(long long root, long long l, long long r, long long index, long long value)
{
if(l == r){
node[root] = value;
return ;
}
long long mid = (l + r) >> 1;
PushDown(root, mid - l + 1, r - mid);
if(index <= mid)
Update(root<<1, l, mid, index, value);
else
Update(root<<1|1, mid + 1, r, index, value);
PushUp(root);
}
inline void Update(long long root, long long l, long long r, long long L, long long R, long long value)
{
if(L <= l && r <= R){
node[root] += value;
lazy[root] += value;
return ;
}
long long mid = (l + r) >> 1;
PushDown(root, mid - l + 1, r - mid);
if(L <= mid)
Update(root<<1, l, mid, L, R, value);
if(R > mid)
Update(root<<1|1, mid + 1, r, L, R, value);
PushUp(root);
}
inline long long Query(long long root, long long l, long long r, long long L, long long R)
{
if(L <= l && r <= R){
return node[root];
}
long long mid = (l + r) >> 1;
PushDown(root, mid - l + 1, r - mid);
long long ans = 0;
if(L <= mid)
ans = max(ans, Query(root<<1, l, mid, L, R));
if(R > mid)
ans = max(Query(root<<1|1, mid + 1, r, L, R), ans);
return ans;
}
//
struct p
{
long long x;
long long y;
long long a;
long long b;
friend bool operator <(const p as, p bs)
{
return (as.x == bs.x) ? as.y > bs.y : as.x < bs.x;
}
};
/*
long long cmp(p as, p bs)
{
return (as.x == bs.x) ? as.y > bs.y : as.x < bs.x;
}
*/
int main()
{
ios::sync_with_stdio(false);
long long n;
while(cin >> n){
vector<p> nodeVe;
vector<long long> nVe;
long long x, y, a, b;
for(long long i = 1; i <= n; i++){
cin >> x >> y >> a >> b;
nodeVe.push_back(p{x, y, a, b});
nVe.push_back(y); //存在y, 后面对其进行离散化
}
sort(nVe.begin(), nVe.end());
nVe.erase(unique(nVe.begin(), nVe.end()), nVe.end());
//对Y进行离散化
for(long long i = 0; i < n; i++){
nodeVe[i].y = lower_bound(nVe.begin(), nVe.end(), nodeVe[i].y) - nVe.begin() + 1;
}
//sort(nodeVe.begin(), nodeVe.end(), cmp);
sort(nodeVe.begin(), nodeVe.end());
//建树,并初始化0,
long long nTreeSize = nVe.size();
BuildTree(1, 0, nTreeSize); // 因为我们是y来进行dp, 所以树的大小就是nVe.size();
//维护区间最值
for(long long i = 0; i < n; i++){
//修改这个点贡献即 dp[i]
Update(1, 0, nTreeSize, nodeVe[i].y, Query(1, 0, nTreeSize, 0, nodeVe[i].y) + nodeVe[i].b);
//更新左子树,右子树
if(nodeVe[i].y - 1 >= 0) Update(1, 0, nTreeSize, 0, nodeVe[i].y - 1, nodeVe[i].a);
if(nodeVe[i].y + 1 <= nTreeSize) Update(1, 0, nTreeSize, nodeVe[i].y + 1, nTreeSize, nodeVe[i].b);
}
cout << node[1] << endl;
}
return 0;
}