[HEOI2016/TJOI2016]序列 CDQ分治
题解:
首先我们观察一下,如果一个点对(j, i),
要符合题中要求要满足哪些条件?
首先我们设 j < i
那么有:
j < i
max[j] < v[i]
v[j] < min[i]
(注意下面两个式子都是用的v[i],v[j],,,而不是i , j。。。之前因为这个问题纠结了很久,其实我也不知道我在纠结什么。。。)
这三个式子是不是很眼熟?
如果式子变成:
j < i
max[j] < max[i]
min[j] < min[i]
是不是就和三维偏序一模一样了?
但是还是略有区别,不过区别不大,所以我们考虑一个变种的三维偏序。
在之前的板子中我用的是归并排序。
但由于这个题目式子不同。所以归并排序不在合适
首先CDQ可以保证id的相对有序。
而为了比较max[j] 和 v[i]
我们使用sort,分别对左边按max排序,对右边按id排序。
为了比较v[j] < min[i]
我们使用树状数组,
在满足max[j] < v[i]的条件下,
在树状数组的第v[j]位插入大小为ans[j]的数。
查询时用min[i]查询。
树状数组维护最大值(此时不满足区间减法)
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 100100
#define getchar() *o++
#define lowbit(x) (x & (-x))
#define D printf("line in %d\n", __LINE__);
char READ[], *o = READ;
/*变种三维偏序,
总的来说就是要保证这三个式子。
i < j
max[j] < v[i]
v[j] < min[i]
可以看出的三维偏序是非常类似的,
所以也可以用CDQ + 归并 + 树状数组实现。
CDQ维护下标,也就是第一个式子
归并维护第二个式子,
树状数组用于在归并的条件下查询满足第3个式子的贡献。
本质上是类似DP的东西?
p[i].ans 表示以i为结尾的子序列的最长长度
*/
/*初始状态下id相对有序,归并维护maxj的顺序
但是这个好像和原来的不一样???
原来的是维护maxj < maxi,两边都是一样的属性,
所以归并完就排好了,因为它的要求对于左边和右边而言是一样的,
都是要按maxj排序,这样的话归并一遍,等到回去的时候这个小块就是按maxj排好序的。
就符合上面的要求。
但是这个maxj < i,两边是不同的属性,所以不太适用。。。
因为这样的话要求小块处理完后左边是按照maxnj排序的,而右边却是按照i排序的。
因此这就不便于处理,也就是根本不能排。
而且这里左边对右边的贡献是有顺序限制的,因此小块处理也要分开
还是要用sort啊......*/
int n, m, ans, maxn;
int power[AC], tmp[AC], c[AC];
struct node{
int id, max, min, ans, v;
}p[AC]; inline int read()
{
int x = ; char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void upmin(int &a, int b)
{
if(a > b) a = b;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} inline bool cmp1(node a, node b)//按max排序
{
return a.max < b.max;
} inline bool cmp2(node a, node b)//v排序
{
return a.v < b.v;
}
//按id排序,因为右边块的调用是在处理完左边和左边对右边的贡献后的,
inline bool cmp3(node a, node b)//而这时右边已经不在是id有序的状态了,(因为按v排了序),但是又要求id有序,所以还要还原一次
{
return a.id < b.id;
} //min由树状数组负责
void pre()
{
int a, b;
n = read(), m = read();
for(R i = ; i <= n; i++)
{
p[i].id = i;
p[i].v = p[i].max = p[i].min = read();
}
for(R i = ; i <= m; i++)
{
a = read(), b = read();
upmax(p[a].max, b);
upmax(maxn, b);
upmin(p[a].min, b);
}
} inline void add(int x, int w)//维护前缀最大值的树状数组(不符合区间减法)
{
for(R i = x; i <= maxn; i += lowbit(i)) upmax(c[i], w);//维护最大值
}//因为维护的格子是以v[i]为基础的,存的东西是ans[i],所以上界自然是max(v[i]) inline int sum(int x)//查询前缀最大值
{
int ans = ;
for(R i = x; i ; i -= lowbit(i)) upmax(ans, c[i]);
return ans;
} inline void clear(int x)
{
for(R i = x; i <= maxn; i += lowbit(i)) c[i] = ;
} void CDQ(int l, int r)
{
if(l < r)
{
int mid = (l + r) >> ;
CDQ(l, mid);
sort(p + l, p + mid + , cmp1);//按max排序
sort(p + mid + , p + r + , cmp2);//按v排序
int i = l, j = mid + ;
while(j <= r)//因为要靠这个代替内层循环,所以这个要用||,但是又不能直接用||,因为会导致死循环(i一直不符合条件)
{//j一直往后走,因此直接判断j,相当于外层只是控制j的
while(p[i].max <= p[j].v && i <= mid) add(p[i].v, p[i].ans), ++i;
upmax(p[j].ans, sum(p[j].min) + ), ++j;//还要加上自己,因为i往后移动了,所以这个时候再判断大小就不对了,所以干脆强制转移
} //让外层循环代替内层循环
for(R k = l; k <= i; k++) clear(p[k].v);//error!!!放进去了多少就拿出来多少,不然就浪费了
sort(p + mid + , p + r + , cmp3);//还原id
CDQ(mid + , r);//因为这个要统计最长长度,是有先后顺序的,陌上花开是在统计个数,是可以允许没有顺序的
}
else upmax(p[l].ans, );//最少也是1了
} void work()
{
for(R i = ; i <= n; i++) upmax(ans, p[i].ans);
printf("%d\n", ans);
// printf("time used... %lf\n", (double)clock()/CLOCKS_PER_SEC);
} int main()
{
// freopen("in.in", "r", stdin);
fread(READ, , , stdin);
pre();
CDQ(, n);
work();
// fclose(stdin);
return ;
}
[HEOI2016/TJOI2016]序列 CDQ分治的更多相关文章
- 洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP
洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...
- 【洛谷P4093】 [HEOI2016/TJOI2016]序列 CDQ分治+动态规划
你发现只会改变一个位置,所以可以直接进行dp 具体转移的话用 CDQ 分治转移就好了~ #include <bits/stdc++.h> #define N 100006 #define ...
- BZOJ4553/洛谷P4093 [HEOI2016/TJOI2016]序列 动态规划 分治
原文链接http://www.cnblogs.com/zhouzhendong/p/8672434.html 题目传送门 - BZOJ4553 题目传送门 - 洛谷P4093 题解 设$Li$表示第$ ...
- cdq分治(hdu 5618 Jam's problem again[陌上花开]、CQOI 2011 动态逆序对、hdu 4742 Pinball Game、hdu 4456 Crowd、[HEOI2016/TJOI2016]序列、[NOI2007]货币兑换 )
hdu 5618 Jam's problem again #include <bits/stdc++.h> #define MAXN 100010 using namespace std; ...
- 洛谷 P4093 [HEOI2016/TJOI2016]序列 解题报告
P4093 [HEOI2016/TJOI2016]序列 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一 ...
- 【BZOJ4553】[Tjoi2016&Heoi2016]序列 cdq分治+树状数组
[BZOJ4553][Tjoi2016&Heoi2016]序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值可能 ...
- [BZOJ4553][TJOI2016&&HEOI2016]序列(CDQ分治)
4553: [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 554[Su ...
- [BZOJ4553][HEOI2016]序列 CDQ分治
4553: [Tjoi2016&Heoi2016]序列 Time Limit: 20 Sec Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小伙 ...
- 洛谷 P4093 [HEOI2016/TJOI2016]序列(Cdq+dp)
题面 luogu 题解 \(Cdq分治+dp\) \(mx[i],mn[i]\)分别表示第\(i\)位最大,最小能取到多少 那么有 \(j < i\) \(mx[j] \le a[i]\) \( ...
随机推荐
- journalctl 日志查看方法
1 概述 日志管理工具journalctl是centos7上专有的日志管理工具,该工具是从message这个文件里读取信息.Systemd统一管理所有Unit的启动日志.带来的好处就是,可以只用jo ...
- Typeahead的使用总结
Typeahead是Bootstrap的自动补全JS插件. 最近项目中用到,总结一下. 与autocomplish类似,通过ajax实现,实现流程是前台输入关键字,后台根据关键字查询出信息,构造jso ...
- 说说CakePHP的关联模型之一 基本关联
一个无论多么复杂的程序,拆开看无非是三种逻辑结构的组合:顺序结构.条件结构和循环结构. 类似的,数据库中表与表的之间的关联无外乎四种:一对一.一对多.多对一和多对多. CakePHP的模型层中定义了四 ...
- shell 批量压缩指定目录及子目录内图片的方法
用户上传的图片,一般都没有经过压缩,造成空间浪费.因此需要编写一个程序,查找目录及子目录的图片文件(jpg,gif,png),将大于某值的图片进行压缩处理. 查看目录文件大小 du -h --max- ...
- ansible基础配置使用(一)
test test test
- hdu1421搬寝室(动态规划)
搬寝室 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- 【转】cocos2dx3.2学习笔记之Director(导演类)
转载:https://blog.csdn.net/u013435551/article/details/38579747 在Cocos2d-x中,把统筹游戏大局的类抽象为导演类(Director),D ...
- 前端开发工程师 - 03.DOM编程艺术 - 第1章.基础篇(下)
第1章.基础篇(下) Abstract: 数据通信.数据存储.动画.音频与视频.canvas.BOM.表单操作.列表操作 数据通信(HTTP协议) HTTP事务: 客户端向服务器端发送HTTP请求报文 ...
- netty in action 笔记 二
netty的数据容器 网络数据的基本单位大多为字节,Java NIO 提供了ByteBuffer 作为它的字节容器,但使用起来过于复杂和繁琐.在Netty中, ByteBuffer 替代品是ByteB ...
- HDU 2494/POJ 3930 Elevator(模拟)(2008 Asia Regional Beijing)
Description Too worrying about the house price bubble, poor Mike sold his house and rent an apartmen ...