2019牛客多校第一场 I Points Division(动态规划+线段树)
传送门:https://ac.nowcoder.com/acm/contest/881/I
题意:
给你n个点,每个点有两个属性a,b
需要将点划分为两堆,划分依据是对于在A划分中的任意点a和在B划分中的任意点b满足
不存在当a.x>b.x时,a.y<b.y 的情况
在A划分中的点可以给出其a属性的贡献,在B划分中的点可以给出其b属性的贡献
求最大贡献和
题解:
根据题意,我们可以得出结论,我们需要找的是一根折线,这根折线将点集分为A、B两部分、
我们需要求这两个部分的最大权值和
我们考虑dp状态
dp[i]表示到第i个点在折线上时和的最大值,如果增加了这个点,他对答案产生的贡献就是,对于之前比这个点高的点,对答案的贡献是ai,对于之前比这个点低的点,对答案的贡献是bi
于是\(d p[j]=\left\{\begin{array}{ll}{d p[j]+b_{i}} & {j<i, y_{j}>y_{i}} \\ {d p[j]+a_{i}} & {j<i, y_{j}<y_{i}}\end{array}\right.\)
\(d p[i]=b_{i}+\max _{1 \leq j<i, y_{j}<y_{i}} d p[j]\)
显然这个式子是可以用线段树维护区间最值的
因为值域范围为1e9,我们将y值离散化后建树,维护的区间最大值就是我们最后的答案
因为dp的值是从0开始的,所以我们建树也是从0开始
排序是为了能够有A,B的合法划分
感谢邱神的博客学习:https://blog.csdn.net/u013534123/article/details/96465704
代码:
#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
LL Max[maxn << 2];
LL lazy[maxn << 2];
void push_up(int rt) {
Max[rt] = max(Max[ls], Max[rs]);
}
void build(int l, int r, int rt) {
Max[rt] = lazy[rt] = 0;
if(l == r) return;
int mid = (l + r) >> 1;
build(lson);
build(rson);
}
void push_down(int rt) {
if(lazy[rt]) {
lazy[ls] += lazy[rt];
lazy[rs] += lazy[rt];
Max[ls] += lazy[rt];
Max[rs] += lazy[rt];
lazy[rt] = 0;
}
}
void update(int L, int R, LL val, int l, int r, int rt) {
if(L <= l && r <= R) {
Max[rt] += val;
lazy[rt] += val;
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if(L <= mid) update(L, R, val, lson);
if(R > mid) update(L, R, val, rson);
push_up(rt);
}
void change(int pos, LL val, int l, int r, int rt) {
if(l == r) {
Max[rt] = val;
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if(pos <= mid) change(pos, val, lson);
else change(pos, val, rson);
push_up(rt);
}
LL query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return Max[rt];
}
push_down(rt);
int mid = (l + r) >> 1;
LL ans = 0;
if(L <= mid) ans = max(ans, query(L, R, lson));
if(R > mid) ans = max(ans, query(L, R, rson));
return ans;
}
struct node {
int x, y, a, b;
} p[maxn];
bool cmp(node a, node b) {
if(a.x != b.x) return a.x < b.x;
return a.y > b.y;
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int n;
while(~scanf("%d", &n)) {
vector<int> vec;
for(int i = 1; i <= n; i++) {
scanf("%d%d%d%d", &p[i].x, &p[i].y, &p[i].a, &p[i].b);
vec.push_back(p[i].y);
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
for(int i = 1; i <= n; i++) {
p[i].y = lower_bound(vec.begin(), vec.end(), p[i].y) - vec.begin() + 1;
}
int tot = vec.size();
sort(p + 1, p + n + 1, cmp);
build(0, tot, 1);
for(int i = 1; i <= n; i++) {
change(p[i].y, query(0, p[i].y, 0, tot, 1) + p[i].b, 0, tot, 1);
if(p[i].y - 1 >= 0) update(0, p[i].y - 1, p[i].a, 0, tot, 1);
if(p[i].y + 1 <= tot) update(p[i].y + 1, tot, p[i].b, 0, tot, 1);
}
printf("%lld\n", Max[1]);
}
return 0;
}
2019牛客多校第一场 I Points Division(动态规划+线段树)的更多相关文章
-
2019牛客多校第一场I Points Division(DP)题解
题意: n个点,分成两组A,B,如果点i在A中,那么贡献值\(a_i\),反之为\(b_i\). 现要求任意\(i \in A,j \in B\)不存在 \(x_i >= x_j\) 且 \(y ...
-
2019牛客多校第一场E ABBA(DP)题解
链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 ABBA 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语 ...
-
2019牛客多校第一场A-Equivalent Prefixes
Equivalent Prefixes 传送门 解题思路 先用单调栈求出两个序列中每一个数左边第一个小于自己的数的下标, 存入a[], b[].然后按照1~n的顺序循环,比较 a[i]和b[i]是否相 ...
-
2019牛客多校第一场 A.Equivalent Prefixes
题目描述 Two arrays u and v each with m distinct elements are called equivalent if and only if RMQ(u,l,r ...
-
2019 牛客多校第一场 D Parity of Tuples
题目链接:https://ac.nowcoder.com/acm/contest/881/D 看此博客之前请先参阅吕凯飞的论文<集合幂级数的性质与应用及其快速算法>,论文中很多符号会被本文 ...
-
2019牛客多校第一场 E-ABBA(dp)
ABBA 题目传送门 解题思路 用dp[i][j]来表示前i+j个字符中,有i个A和j个B的合法情况个数.我们可以让前n个A作为AB的A,因为如果我们用后面的A作为AB的A,我们一定也可以让前面的A对 ...
-
【2019牛客多校第一场】XOR
题意: 给你一个集合A,里边有n个正整数,对于所有A的.满足集合内元素异或和为0的子集S,问你∑|S| n<=1e5,元素<=1e18 首先可以转化问题,不求∑|S|,而是求每个元素属于子 ...
-
2019 牛客多校第一场 B Integration
题目链接:https://ac.nowcoder.com/acm/contest/881/B 题目大意 给定 n 个不同的正整数 ai,求$\frac{1}{\pi}\int_{0}^{\infty} ...
-
2019牛客多校第一场E ABBA 贪心 + DP
题意:问有多少个有(n + m)个A和(n + m)个B的字符串可以凑出n个AB和m个BA. 思路:首先贪心的发现,如果从前往后扫,遇到了一个A,优先把它看成AB的A,B同理.这个贪心策略用邻项交换很 ...
随机推荐
-
microsoft docx document operation with Java POI library
microsoft docx document operation with Java POI library combine multiple docx document into one docu ...
-
[转]oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务。
oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务. 一.查询系统中的job,可以查询视图 --相关视图 select * from dba_jobs; selec ...
-
找回消失的ASUS显卡
笔记本蓝屏了几次之后,发现独立显卡GT335M不见了,设备管理器,驱动精灵,都找不到,网上问这个问题的人还不少,得到的回答几乎都是说重装驱动.根本不行,这时候安装nVIDIA驱动,会提示说“未找到兼容 ...
-
C# JSON to object
/// <summary> /// json格式转换(引用System.Web.Extension类库) /// </summary> /// <param name=& ...
-
Virtualbox 启动虚拟机报错以及扩展、显卡驱动安装
一.Virtualbox虚拟机启动报错,如图 预先估计是BIOS中的cpu Virtualtion虚拟化支持是disable,结果一看是enable. 接下来只好Google,找到了这么一个帖子:ht ...
-
Miniconda 虚拟环境安装及应用
首先要下载Miniconda安装包 下载地址 链接:https://pan.baidu.com/s/1rj-9exKBSHnCCxqq7JQSxA 提取码:ab53 下一步 打开下载好的M ...
-
oracle报错ORA-01653 dba_free_space中没有该表空间
新建了一个表空间t101,在dba_tablespaces和dba_data_files都出现了,在dba_free_space却没有,这个很有可能是表空间满了. 插入数据会报错:ORA-01653: ...
-
别人的Linux私房菜(5)首次CentOS7与帮助等
ctrl alt F1-F6切换终端tty1-6,其中,F1的终端带有用户界面. 在终端登录后,输入startx启动个人图形界面.(启动有一些条件限制,如没有其他的X Window启用,已经安装,并具 ...
-
Couchbase学习和使用
Couchbase介绍 couchbase的关键有两点:延后写入和松散存储.延后写入,顾名思义,couchbase在对数据进行增删时会先体现在内存中,而不会立刻体现在硬盘上,从内存的修改到硬盘的修改这 ...
-
codevs 1077 多源最短路
题目描述 Description 已知n个点(n<=100),给你n*n的方阵,a[i,j]表示从第i个点到第j个点的直接距离. 现在有Q个询问,每个询问两个正整数,a和b,让你求a到b之间的最 ...