loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移
$ \color{#0066ff}{ 题目描述 }$
给出一个长度为 \(n\) 宽度为 \(1\) ,高度无限的水箱,有 \(n-1\) 个挡板将其分为 \(n\) 个 \(1 - 1\) 的小格,然后向每个小格中注水,水如果超过挡板就会溢出到挡板的另一边,这里的水是满足物理定律的(在无挡板阻拦的情况下会向低处流),现在有 \(m\) 个条件 \((i,j,k)\),表示从左到右数的第 \(i\) 个格子中,在高度为 \(y+0.5\) 的地方是否有水, \(k=1\) 表示有水,\(k=0\) 表示没有水,请求出这 \(m\) 个条件最多能同时满足多少个条件。本题有多组数据。
\(\color{#0066ff}{输入格式}\)
第一行一个正整数 \(T\) 为数据组数。
第二行两个正整数 \(n, m\),中间用空格隔开。
接下来一行 \(n-1\) 个整数,表示从左到右每一块隔板的高度。
接下来 \(m\) 行,每行三个整数 \(i,j,k\),表示一个条件。
\(\color{#0066ff}{输出格式}\)
共 \(T\) 行,每行对应一组数据的答案。
\(\color{#0066ff}{输入样例}\)
2
3 4
3 4
1 3 1
2 1 0
2 2 0
3 3 1
2 2
2
1 2 0
1 2 1
\(\color{#0066ff}{输出样例}\)
3
1
\(\color{#0066ff}{数据范围与提示}\)
对于\(20\%\)的数据,\(n,m\le 16\)
对于另外\(10\%\)的数据,只存在指明某处有水的条件
对于另外\(30\%\)的数据,\(n,m\le 1000\)
对于\(100\%\)的数据,\(n,m\le 10^5, T\le 5\)
\(\color{#0066ff}{题解}\)
显然我们可以有一个\(O(n^2)\)的暴力
设\(f[i][j]\)表示从\(1\)到\(i\),且第i格水的高度为j的最大答案
转移的话,如果当前这个没超,就是它根下一个是分开的,那么就有转移\(f[i][j]\to f[i+1][k], j,k\in[0,h[i]]\)
如果超过了,那么就是这两个连在一起了,那么就这样转移\(f[i][j]\to f[i+1][j]\)
然后发现,第一维可以省去,然后在结合转移,发现其实就是两个操作
一个是用\([0,h[i]]\)的最大值更新\([0,h[i]]\)的每一个值,(另一个转移是直接继承,不用管)
还有就是对于每个条件,比如一个条件\(x, 0\),就是说,x的位置没有水,那么显然\(f[0...x]\)这些值都要+1,这是区间加
我们只需要维护一个资瓷区间加,区间取max,区间求max的线段树就行了
注意h要离散化一下qwq
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 5e5 + 10;
const int inf = 0x7fffffff;
struct Tree {
protected:
struct node {
node *ch[2];
int l, r, add, max, val;
node(int l = 0, int r = 0, int add = 0, int max = 0, int val = 0): l(l), r(r), add(add), max(max), val(val) { ch[0] = ch[1] = NULL; }
void trn(int x, int y) { add += x, max = std::max(max + x, y), val = std::max(val + x, y); }
void dwn() {
if(!add && !max) return;
ch[0]->trn(add, max), ch[1]->trn(add, max);
add = max = 0;
}
void upd() { val = std::max(ch[0]->val, ch[1]->val); }
int mid() { return (l + r) >> 1; }
}*root;
void build(node *&o, int l, int r) {
o = new node(l, r);
if(l == r) return;
build(o->ch[0], l, o->mid());
build(o->ch[1], o->mid() + 1, r);
}
void lazy(node *o, int l, int r, int x, int y) {
if(l <= o->l && o->r <= r) return o->trn(x, y);
o->dwn();
if(l <= o->mid()) lazy(o->ch[0], l, r, x, y);
if(r > o->mid()) lazy(o->ch[1], l, r, x, y);
o->upd();
}
int query(node *o, int l, int r) {
if(l <= o->l && o->r <= r) return o->val;
o->dwn(); int ans = 0;
if(l <= o->mid()) ans = std::max(ans, query(o->ch[0], l, r));
if(r > o->mid()) ans = std::max(ans, query(o->ch[1], l, r));
o->upd();
return ans;
}
public:
void add(int l, int r, int x, int y) { if(l <= r) lazy(root, l, r, x, y); }
void init(int n) { root = NULL, build(root, 1, n); }
int query(int l, int r) { return l <= r? query(root, l, r) : 0; }
int getans() { return root->val; }
}T;
int n, m, h[maxn], b[maxn], cnt;
std::vector<int> mp0[maxn], mp1[maxn];
int main() {
for(int S = in(); S --> 0;) {
n = in(), m = in();
h[1] = b[cnt = 1] = inf;
int x, y, z;
for(int i = 1; i <= n; i++) mp0[i].clear(), mp1[i].clear();
for(int i = 2; i <= n; i++) b[++cnt] = h[i] = in();
h[n + 1] = 0;
for(int i = 1; i <= m; i++) {
x = in(), y = in(), z = in();
if(z) mp1[x].push_back(y);
else mp0[x].push_back(y);
b[++cnt] = y, b[++cnt] = y + 1;
}
std::sort(b + 1, b + cnt + 1);
cnt = std::unique(b + 1, b + cnt + 1) - b - 1;
T.init(cnt);
for(int i = 1; i <= n; i++) h[i] = std::lower_bound(b + 1, b + cnt + 1, h[i]) - b;
for(int i = 1; i <= n; i++) {
for(int now : mp0[i]) T.add(1, std::lower_bound(b + 1, b + cnt + 1, now) - b, 1, 0);
for(int now : mp1[i]) T.add(std::lower_bound(b + 1, b + cnt + 1, now) - b + 1, cnt, 1, 0);
T.add(1, h[i + 1], 0, T.query(1, h[i + 1]));
}
printf("%d\n", T.getans());
}
return 0;
}
loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移的更多相关文章
- loj#6032. 「雅礼集训 2017 Day2」水箱(并查集 贪心 扫描线)
题意 链接 Sol 神仙题+神仙做法%%%%%%%% 我再来复述一遍.. 首先按照\(y\)坐标排序,然后维护一个扫描线从低处往高处考虑. 一个连通块的内状态使用两个变量即可维护\(ans\)表示联通 ...
- LOJ#6032. 「雅礼集训 2017 Day2」水箱
传送门 首先可以有一个平方复杂度的 \(DP\) 设 \(f_{i,j}\) 表示前面 \(i\) 个小格,高度为 \(j\) 的最大答案 令 \(h_i\) 表示隔板 \(i\) 的高度 当 \(j ...
- loj#6029. 「雅礼集训 2017 Day1」市场(线段树)
题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...
- LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法
题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...
- loj#6033. 「雅礼集训 2017 Day2」棋盘游戏(二分图博弈)
题意 链接 Sol 第一次做在二分图上博弈的题..感觉思路真是清奇.. 首先将图黑白染色. 对于某个点,若它一定在最大匹配上,那么Bob必胜.因为Bob可以一直沿着匹配边都,Alice只能走非匹配边. ...
- [LOJ#6033]. 「雅礼集训 2017 Day2」棋盘游戏[二分图博弈、匈牙利算法]
题意 题目链接 分析 二分图博弈经典模型,首先将棋盘二分图染色. 考虑在某个最大匹配中: 如果存在完美匹配则先手必败,因为先手选定的任何一个起点都在完美匹配中,而后手则只需要走这个点的匹配点,然后先手 ...
- loj#6034 「雅礼集训 2017 Day2」线段游戏
分析 区间李超树板子题 代码 #include<bits/stdc++.h> using namespace std; #define db double const int inf = ...
- LOJ #6037.「雅礼集训 2017 Day4」猜数列 状压dp
这个题的搜索可以打到48分…… #include <cstdio> #include <cstring> #include <algorithm> ; bool m ...
- 「雅礼集训 2017 Day2」水箱
题目链接 题意分析 我们用\(f[i][j]\)表示当前到达第\(i\)个位置水位高度为\(j\)的答案 如果那么\(h[i]\)为\(i\)和\(i+1\)之间的支柱高度 那么如果\(j≤h[i]\ ...
随机推荐
- redis 面试题1 有用
1.什么是redis? Redis 是一个基于内存的高性能key-value数据库. 2.Reids的特点 Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库 ...
- EZOJ #224
传送门 分析 首先我们发现要让答案最小,或运算一定是没有用的 我们还可以发现a^b = a&(~b) 所以异或运算也没有用 于是我们只考虑否和与 我们还会得到一个性质就是没增加一个数一定会让答 ...
- perl读取excel
因为工作当中遇到要处理大数据的excel的玩意,最多的有几十万行.用perl的方式试试,看看效果如何. ppm install OLE::Storage_Lite #如果不安装这个,后面两个安装不了 ...
- linux系统学习(一)
查看linux版本信息:http://distrowatch.com/ linux根目录下系统文件夹的含义 /boot 该目录下默认存放的是linux的启动文件和内核,一般200M swap交换分区, ...
- FCKEditor2.x整合教程-Xproer.WordPaster
版权所有 2009-2017 荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webplug/wordpa ...
- O_DIRECT方式读取文件示例
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h& ...
- MATLAB搬移到别的电脑出现License Manager Error -9
是注册码的问题,不需要重装,主要是以前的安装包不见了.解决办法: 下一个KeyGen的MLMCrypt.exe文件.运行之后在当前目录下出现一个LICENSE.DAT文件. 复制到matlab.exe ...
- struts整合dropzone.js上传图片遇到的点问题
问:struts后台无法获取文件对象和文件名称? 答:1. 到dropzone.js搜索"return xhr.send(formData);" 2. 在它前面有个这么句代码: f ...
- C++/Java中继承关系引发的调用关系详解
C++: 这里引用到了 http://blog.csdn.net/haoel/article/details/1948051/ 中的内容,还请提前阅读陈大神的这篇博客后在阅读本篇. 覆盖,实现多态的基 ...
- 基于行块分布函数的通用网页正文内容抽取(带HTML格式)
算法思路: 假如网页正文(过滤html标签后的)有n行,以k行为一行块,总共可构成n-k+1行块: 以行号为索引号,以行块长度为索引值,形成行块稀疏矩阵: 以上面的稀疏矩阵为基础,找出其骤升骤降点,分 ...