Boring Class HDU - 5324 (CDQ分治)
Here is the problem:
Give you two sequences L1,L2,...,Ln and R1,R2,...,Rn.
Your task is to find a longest subsequence v1,v2,...vm satisfies
v1≥1,vm≤n,vi<vi+1 .(for i from 1 to m - 1)
Lvi≥Lvi+1,Rvi≤Rvi+1(for i from 1 to m - 1)
If there are many longest subsequence satisfy the condition, output the sequence which has the smallest lexicographic order.
InputThere are several test cases, each test case begins with an integer n.
1≤n≤50000
Both of the following two lines contain n integers describe the two sequences.
1≤Li,Ri≤109
OutputFor each test case ,output the an integer m indicates the length of the longest subsequence as described.
Output m integers in the next line.
Sample Input
5
5 4 3 2 1
6 7 8 9 10
2
1 2
3 4
Sample Output
5
1 2 3 4 5
1
1 题意
给你两个序列Li,Ri,求构造一个最长的子序列,使得L递减, R递增。在保证最长的前提下要求字典序最小。(vj)
思路:
很明显的可以看出是三维偏序问题。
但是这题要求的是最长的序列,而不是对于每一个元素求解,所以需要要对CDQ分治的部分做相应的更改。
我们设对每一个元素,求以它未开始的符合题意的序列长度最长是多长。只有这样,才能顺利求出字典序最小。
那么对于每一个元素,在处理其答案时,其右侧的元素答案都应该已知了。
传统分治的做法显然不能满足这个要求,因为在如果先治左边,那么右边未知,便无法知道答案。
于是我们想到先分治右侧,再分治左侧。
但是这还不够,在对左侧求解过程中,当前右侧的答案可能并非是全局的答案,这一点的原因我不知道该如何描述,但是在3层CDQ里面就已经很明显了。
所以我们先分治右边,在处理当前层,再分治左边。
由于分治顺序的特殊性,归并排序已经不适用了,所以只能使用快排。
注意在处理左侧之前,要回复左侧原来的顺序。
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime> #define fuck(x) clog<<#x<<" = "<<x<<endl;
#define debug(a, x) clog<<#a<<"["<<x<<"] = "<<a[x]<<endl;
#define lson l,mid,ls
#define rson mid+1,r,rs
#define ls (rt<<1)
#define rs ((rt<<1)|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int loveisblue = ;
const int maxn = ;
const int maxm = ;
const int inf = 0x3f3f3f3f;
const ll Inf = ;
const int mod = ;
const double eps = 1e-;
const double pi = acos(-); int n;
struct node{
int a,b,c,ans;
}cdq[maxn];
int mx[maxn<<];
void update(int l,int r,int rt,int pos,int val){
if(l==r){
mx[rt]=val;
return;
}
int mid = (l+r)>>;
if(pos<=mid){
update(lson,pos,val);
}else{
update(rson,pos,val);
}
mx[rt]=max(mx[ls],mx[rs]);
} int query(int l,int r,int rt,int L,int R){
if(L<=l&&R>=r){
return mx[rt];
}
int ans = ;
int mid = (l+r)>>;
if(L<=mid){
ans= max(ans,query(lson,L,R));
}if(R>mid){
ans = max(ans,query(rson,L,R));
}
return ans;
}
int num[maxn];
int rem[maxn],tot;
int get_id(int x){
return lower_bound(rem+,rem++tot,x)-rem;
} bool cmp1(node a,node b){
if(a.b!=b.b)return a.b>b.b;
return a.c<b.c;
}
bool cmp(node a,node b){
return a.a<b.a;
} void solve(int l,int r){
if(l==r){ return;}
int mid = (l+r)>>;
solve(mid+,r);
int t1 = mid,t2 = r;
int cur = r+;
sort(cdq+l,cdq+mid+,cmp1);
sort(cdq+mid+,cdq+r+,cmp1);
while (t1>=l||t2>mid) {
if (t1 < l || (t2 > mid && cdq[t1].b >= cdq[t2].b)) {
update(, tot, , get_id(cdq[t2].c), cdq[t2].ans);
t2--;
} else {
cdq[t1].ans = max(cdq[t1].ans, query(, tot, , get_id(cdq[t1].c) ,tot)+);
t1--;
}
}
for(int i=mid+;i<=r;i++){
update(,tot,,get_id(cdq[i].c),);
}
sort(cdq+l,cdq+mid+,cmp);
solve(l,mid);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while (scanf("%d",&n)!=EOF) {
tot = ;
for (int i = ; i <= n; i++) {
scanf("%d", &num[i]);
}
for (int i = ; i <= n; i++) {
int x;
scanf("%d", &x);
rem[++tot] = x;
cdq[i] = node{i, num[i], x, };
}
sort(rem+,rem++tot);
tot = unique(rem+,rem++tot)-rem-;
solve(,n);
sort(cdq+,cdq++n,cmp);
int ans = ;
for(int i=;i<=n;i++){
ans = max(cdq[i].ans,ans);
}
printf("%d\n",ans);
int last = ;
cdq[].b = inf;
cdq[].c = -;
for(int i=;i<=n;i++){
if(cdq[i].ans==ans&&cdq[i].b<=cdq[last].b&&cdq[i].c>=cdq[last].c){
ans--;
last=i;
if(ans==){printf("%d\n",i);}
else printf("%d ",i);
}
}
}
return ;
}
Boring Class HDU - 5324 (CDQ分治)的更多相关文章
- HDU 5324 Boring Class【cdq分治】
这就是一个三维排序的问题,一维递减,两维递增,这样的问题用裸的CDQ分治恰好能够解决. 如同HDU 4742(三维排序,一个三维都是递增的) 由于最小字典序比較麻烦,所以要从后面往前面做分治.每一个点 ...
- HDU - 5324:Boring Class (CDQ分治&树状数组&最小字典序)
题意:给定N个组合,每个组合有a和b,现在求最长序列,满足a不升,b不降. 思路:三位偏序,CDQ分治. 但是没想到怎么输出最小字典序,我好菜啊. 最小字典序: 我们倒序CDQ分治,ans[i]表 ...
- 2015 Multi-University Training Contest 3 hdu 5324 Boring Class
Boring Class Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tota ...
- HDU 3507 Print Article(CDQ分治+分治DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3507 [题目大意] 将长度为n的数列分段,最小化每段和的平方和. [题解] 根据题目很容易得到dp ...
- HDU 5730 Shell Necklace(CDQ分治+FFT)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5730 [题目大意] 给出一个数组w,表示不同长度的字段的权值,比如w[3]=5表示如果字段长度为3 ...
- hdu 3842 Machine Works(cdq分治维护凸壳)
题目链接:hdu 3842 Machine Works 详细题解: HDU 3842 Machine Works cdq分治 斜率优化 细节比较多,好好体会一下. 在维护斜率的时候要考虑x1与x2是否 ...
- hdu 5830 FFT + cdq分治
Shell Necklace Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)T ...
- 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; ...
- 【 HDU - 4456 】Crowd (二维树状数组、cdq分治)
BUPT2017 wintertraining(15) #5A HDU 4456 题意 给你一个n行n列的格子,一开始每个格子值都是0.有M个操作,p=1为第一种操作,给格子(x,y)增加z.p=2为 ...
随机推荐
- Effective Modern C++:06lambda表达式
lambda表达式实际上是语法糖,任何lambda表达式能做到的,手动都能做到,无非是多打几个字.但是lambda作为一种创建函数对象的手段,实在太过方便,自从有了lambda表达式,使用复杂谓词来调 ...
- MaxCompute问答整理之6月
本文是基于本人对MaxCompute产品的学习进度,再结合开发者社区里面的一些问题,进而整理成文.希望对大家有所帮助,下面咱们正式开始. 1.什么是MaxCompute呢?MaxCompute是由阿里 ...
- 【JZOJ4890】【NOIP2016提高A组集训第14场11.12】随机游走
题目描述 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己 ...
- 干货|Spring Cloud Bus 消息总线介绍
继上一篇 干货|Spring Cloud Stream 体系及原理介绍 之后,本期我们来了解下 Spring Cloud 体系中的另外一个组件 Spring Cloud Bus (建议先熟悉 Spri ...
- @loj - 2507@ 「CEOI2011」Matching
目录 @description@ @solution@ @accepted code@ @details@ @description@ 对于整数序列 \((a_1, a_2, ..., a_n)\) ...
- PostgreSQL重新读取pg_hba.conf文件
PostgreSQL 配置文件之pg_hba.conf 该文件用于控制访问安全性,管理客户端对于PostgreSQL服务器的访问权限,内容包括:允许哪些用户连接到哪个数据库,允许哪些IP或者哪个网段 ...
- Android7.0 添加快速设定Quick Settings Tile
Android7.0新推出了一个非常实用的功能--添加快速设定(或者翻译成快速设置),但是感觉社区里关注的人比较少,可能目前为止国内还没有Android7.0的手机,但是越早接触越好,甚至可以告诉产品 ...
- PHP判断图片格式的七种方法小结
<?php $imgurl = "http://www.jb51.net/images/logo.gif"; //方法1 echo $ext = strrchr($imgur ...
- javascript内置函数
1.Date:日期函数属性(1):constructor 所修立对象的函数参考prototype 能够为对象加进的属性和方法办法(43):getDay() 返回一周中的第几天(0-6)getYear( ...
- Android中后台线程如何与UI线程交互
我想关于这个话题已经有很多前辈讨论过了.今天算是一次学习总结吧. 在android的设计思想中,为了确保用户顺滑的操作体验.一些耗时的任务不能够在UI线程中运行,像访问网络就属于这类任务.因此我们必须 ...