[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]\) \( ...
随机推荐
- SpringBoot入门(四)——自动配置
本文来自网易云社区 SpringBoot之所以能够快速构建项目,得益于它的2个新特性,一个是起步依赖前面已经介绍过,另外一个则是自动配置.起步依赖用于降低项目依赖的复杂度,自动配置负责减少人工配置的工 ...
- 获取项目中.txt 文件的内容
package com.fh.controller.ruitai.util; import java.io.BufferedInputStream; import java.io.File; impo ...
- 「题目代码」P1066~P1070(Java)
P1066 谭浩强C语言(第三版)习题8.6 import java.util.*; import java.io.*; import java.math.*; import java.lang.Ch ...
- hdu1596find the safest road(floyd)
find the safest road Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- C 进制 类型说明符 位运算 char类型
一 进制 1. 什么是进制 是一种计数的方式 数值的表示形式 2. 二进制 1> 特点: 只有0和1 逢2进1 2> 书写格式: 0b或者0B开头 3> %d 以带符号的十进制形式输 ...
- Objective-C 第一个小程序
示例一 (类似C) //1.代码编写 //跟C语言一样,OC程序的入口依然是main函数,只不过写到一个.m文件中.比如这里写到一个main.m文件中(文件名可以是中文) #include <s ...
- html简约风用户登录界面网页制作html5-css-jquary-学习模版
2018--12-12 喜迎双十二,咳咳,,,,我不是打广告哈,购物的节日也不要忘记学习. 大家好,我又来了. 今天抽出来空把自己的学习心得给大家分享,这是一个可开发可扩展的用户登录界面,用于开发学习 ...
- 微信小程序 选项 、时间日期选择器
wxml: <view class="section" > <picker bindchange="bindPickerChange" val ...
- [Clr via C#读书笔记]Cp19可空值类型
Cp19可空值类型 主要解决的是和数据库中null对应的问题: System.Nullable结构:值类型: int?语法: 可空实例能够使用操作符: C#空合并操作符??; 即可用于引用类型,也可以 ...
- 吴恩达j机器学习之过拟合
五.编程作业: 见:https://www.cnblogs.com/tommyngx/p/9933803.html