hdu 5324 Boring Class 2015多校联合训练赛3 分治,最长不降子序列,最小字典序
来源:互联网 发布:网络购物经营现状 编辑:程序博客网 时间:2024/06/15 13:33
Boring Class
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 354 Accepted Submission(s): 75
Here is the problem:
Give you two sequences
Your task is to find a longest subsequence
If there are many longest subsequence satisfy the condition, output the sequence which has the smallest lexicographic order.
Both of the following two lines contain n integers describe the two sequences.
Output m integers in the next line.
55 4 3 2 16 7 8 9 1021 23 4
51 2 3 4 511
求最长不降子序列。满足 Li >= Li+1 and Ri <= Ri+1
题解说可以用分治和树套树写,我先用set写,发现set不能完成二维上的查询。然后用splay写,超时了。
树套树还不懂怎么做到的空间,这里只会n^2的空间的方法。
本文采用分治方法:
由于保证最小字典序,则从后往前做,把大小关系取反,求最长上升子序列。
如果求出最长上升子序列,那么从左到右。如果最长长度为ans,遇到第一个满足len = ans的点输出,然后ans--,记录上一次输出的点p,再遇到len = ans的点q,满足p.l >=q.l and p.r <= q.r 就输出q点位置,然后ans--以此类推。
分治求最长上升子序列的方法。
------------------------------点已经逆序排序了
遇到[L,R]区间,先处理左区间,
LLLLLLRRRRRR
然后将R的id值 取反,R只能从L中传递过去更新len值,
用新数组保存这些点,按L从小到大排序(逆序,所以从小到大),如果L相同则id值大的排前面。
从左到右枚举:
遇到id值 > 0的点p在线段树中p.r 中插入该点的len值(取最大的)
遇到id值 < 0 的点p查询满足r>=q.r中len最大的值,+1即更新len[p.id]
然后处理右区间
这样做,R先从L转移了。如果R要从R中点转移,因为最后才处理右区间,所以也会计算到的。
ps:线段树懒标记,方便情况,r要离散化,不然线段树保存不了
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<math.h>using namespace std;#define maxn 200007int lz[maxn],lc[maxn],rc[maxn],val[maxn];int treecnt = 0;void build(int u,int l,int r){ if(l == r) return ; lc[u] = treecnt++; rc[u] = treecnt++; int mid = (l+r)/2; build(lc[u],l,mid); build(rc[u],mid+1,r);}void push_down(int u){ if(lz[u]){ lz[u] = 0; if(rc[u] != 0) lz[rc[u]] = 1,val[rc[u]] = 0; if(lc[u] != 0) lz[lc[u]] = 1,val[lc[u]] = 0; }}void update(int u){ val[u] = max(val[rc[u]],val[lc[u]]);}int query(int u,int l,int r,int pp){ push_down(u); if(l >= pp) return val[u]; int mid = (l+r)/2; if(pp >= mid+1) return query(rc[u],mid+1,r,pp); return max(query(lc[u],l,mid,pp),query(rc[u],mid+1,r,pp));}void add(int u,int l,int r,int pp,int num){ if(l == r){ if(lz[u]) val[pp] = 0; lz[u] = 0; val[u] = max(val[u],num); return ; } push_down(u); int mid = (l+r)/2; if(pp >= mid+1) add(rc[u],mid+1,r,pp,num); else add(lc[u],l,mid,pp,num); update(u);}struct Node{ int l,r,id;};Node p[maxn];Node q[maxn];Node w[maxn];int comp(Node a,Node b){ return a.r < b.r;}int comp1(Node a,Node b){ return a.id > b.id;}int comp3(Node a,Node b){ if(a.l == b.l) return a.id > b.id; return a.l < b.l;}int len[maxn];void fenzhi2(int l,int r){ if(r < l) return ; sort(q+l,q+r+1,comp3); for(int i = l;i <= r; i++){ int id = abs(q[i].id); if(q[i].id < 0){ len[id] = max(len[id],1+query(1,1,50000,q[i].r)); } else { add(1,1,50000,q[i].r,len[id]); } } lz[1] = 1; val[1] = 0;}void fenzhi(int l,int r){ if(l == r) { len[p[l].id] = max(len[p[l].id],1); return ; } int mid = (l+r)/2; fenzhi(l,mid); for(int i = l;i <= r; i++){ q[i] = p[i]; if(i > mid) q[i].id *= -1; } fenzhi2(l,r); fenzhi(mid+1,r);}int comp2(Node a,Node b){ return a.id < b.id;}int main(){ int n; //freopen("1009.in","r",stdin); //freopen("10091.out","w",stdout); while(scanf("%d",&n)!=EOF){ for(int i = 0;i < n;i++){ scanf("%d",&p[i].l); p[i].id = i+1; } for(int i = 0;i < n; i++){ scanf("%d",&p[i].r); } sort(p,p+n,comp); int cnt = 1,r = p[0].r; for(int i = 0;i < n; i++){ if(p[i].r == r) p[i].r = cnt; else { r = p[i].r; p[i].r = ++cnt; } } sort(p,p+n,comp1); memset(len,0,sizeof(len)); memset(lz,0,sizeof(lz)); memset(val,0,sizeof(val)); memset(lc,0,sizeof(lc)); memset(rc,0,sizeof(rc)); treecnt = 2; build(1,1,50000); fenzhi(0,n-1); int ans =0; for(int i = 1;i <= n; i++){ ans = max(ans,len[i]); } sort(p,p+n,comp2); Node x; int flag = 1,be=-1; printf("%d\n",ans); for(int i = 0;i < n; i++){ if(ans == len[p[i].id]){ if(be == -1 || (p[i].l <= p[be].l && p[i].r >= p[be].r)){ if(flag == 0) printf(" "); printf("%d",p[i].id); flag = 0; ans--; be = i; } } } printf("\n"); } return 0;}
- hdu 5324 Boring Class 2015多校联合训练赛3 分治,最长不降子序列,最小字典序
- hdu 4899 Hero meet devil 2014多校联合训练赛 状态压缩dp 最长公共子序列
- 最长不降子序列
- 最长不降子序列
- HDU 5265 序列变换 —— 最长不降子序列
- 最长不降子序列问题
- 最长不降子序列---dp
- 求最长不降子序列
- 最长不降子序列优化
- HDU 5324 Boring Class【cdq分治】
- HDU 5324 Boring Class(CDQ分治)
- Hdu 5324 Boring Class (cdq分治)
- HDU 1950(Bridging signals)最长不降子序列nlogn
- HDU 1257(最少拦截系统)最长不降子序列
- HDU 5807(Revenge of LIS II)最长不降子序列
- hdu 5324 Boring Class(15多校第三场1009)(cdq分治)
- PKU1631Bridging signals(最长不降子序列)
- 最长不降子序列 NlogN解法
- android andbase日期选择器实现及原理
- 第2讲:Scala函数定义、流程控制、异常处理入门
- php引用php文件
- Palindrome Linked List
- 软件开发模型
- hdu 5324 Boring Class 2015多校联合训练赛3 分治,最长不降子序列,最小字典序
- 实用SQL语句
- mysql优化之索引建立的规则
- 如何理解CMMI-DEV模型中的VER与VAL、及PPQA
- python内置函数(二)
- Linux C中的编码转换(文件中文输出)
- ZOJ 3452 Doraemon's Stone Game
- Shell命令:echo 命令详解
- hibernate的级联删除特性