[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]\) \( ...
随机推荐
- 虚拟机ubuntu使用串口
1. 电脑的串口默认是在windows系统上,需要把串口转到ubuntu上面,按照下面的步骤先 2. 找到需要使用的串口 3. 在VMWARE里面连接该串口 或者使用方法 4. 成功之后,检查一下ls ...
- Fat Jar - Myeclipse插件安装使用方法- 完美解决
Eclipse可以安装一个叫Fat Jar的插件,用这个插件打包非常方便,Fat Jar的功能非常强大. 工具/原料 Eclipse Kepler Fat Jar 方法/步骤 1 Fat Jar功能非 ...
- generator-ivweb 基于react-redux的多页脚手架
背景 每个公司甚至每个项目组,在开发新项目的时候都会有一些自己特色的东西,比如公共组件,ajax请求拦截处理,内部积累的一些业务逻辑等等,如果没有自己的脚手架,那么拷贝代码成为常态,每个项目的结构,甚 ...
- VIN码识别,车架号识别,OCR扫描工具
近年二手车交易市场火爆,对二手车估值需要了详细解二手车的历史状况,车架号(VIN码)是车辆唯一的身份标识,也是了解二手车车况的入口,车商和二手车平台会频繁的进行车况查询,VIN码扫描识别技术给车辆估值 ...
- OSG-交互
本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...
- OSG-基本几何图形
本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...
- jenkins--Jenkins+Git+coding+maven 实现自动化测试持续集成
1.打开Jenkins官网,下载jenkins.war https://jenkins.io/download/ 2.将该war包直接放置到Tomcat的webapp下. 3.查看自己Tomcat的端 ...
- Python学习笔记(一)一一一环境安装错误总结
第三方库安装 1 windows存在多个版本的python,pip安装Python库失败 解决方案:进入对应官网下载安装包,步骤:1 下载安装包到C:\Python36\Lib\site-pack ...
- Linux命令应用大词典-第22章 GRUB
22.1 grub-md5-crypt:使用MD5格式加密口令 22.2 grub-install:在设备上安装GRUB 22.3 grub:进入GRUB命令shell 22.4 grub-crypt ...
- Linux命令应用大词典-第 15章 文件、目录权限和属性
15.1 chmod:更改文件和目录的模式 15.2 chown:更改文件和目录的用户所有者和组群所有者 15.3 chgrp:更改文件或目录的所属组 15.4 umask:显示和设置文件及目录创建默 ...