hdu 5324 Boring Class cdq分治+树状数组+离散化
来源:互联网 发布:二手车 知乎 编辑:程序博客网 时间:2024/05/21 07:48
题意:
给你两个序列,两个序列都有n个数。然后让你找到一个位置序列,对应到两个序列上,使得新的L序列非递增,R序列非递减。
问你最长的长度是多少,并输出字典序最小的方案。
思路:
人生的第一道cdq分治,一直觉得这些类型学会了放在比赛也做不出来就没去学了。。。但看到辣么多人会做。。。赶紧搞起。
思路、代码盗自别人blog:http://blog.csdn.net/u013007900/article/details/47111319
由于值太大,先把L、R序列的值都离散化。
首先定义dp[i]:以第i个数为开头的最长长度是多少。(已经定义出dp状态,如果n^2能过,直接dp就可搞了hhh。)
由于要求字典序最小,因此要从后面搞起。如果从前面搞起,dp[i]状态就应该定义为 以第i个数结尾的最长长度,就算让你找到最长长度,但很难得知字典序最小的那个。
大概过程:
先把序列一分为二,既然是从后面搞起,则先把右区间递归搞掉,搞完右区间,然后利用树状数组更新对左区间的影响,清空树状数组后再递归搞左区间。(由于L序列要求非递增,则利用树状数组来保存比当前Li小的Lj的dp最大值。)
最后,我相信不会cdq的还是不知道怎么写,去看代码吧,少年。
code:
#include <bits/stdc++.h>using namespace std;const int N = 5e4+5;typedef long long LL;struct PP { int l, r; int id; bool operator < (const PP &cmp) const { if(r != cmp.r) return r < cmp.r; if(l != cmp.l) return l > cmp.l; //nothing return id < cmp.id; }}a[N];PP p1[N], p2[N];int n, tn;int bit[N<<1];int ls[N<<1];int dp[N];void update(int x, int val) { while(x <= tn) { bit[x] = max(bit[x], val); x += x&(-x); }}int query(int x) { int ret = 0; while(x > 0) { ret = max(ret, bit[x]); x -= x&(-x); } return ret;}void clear(int x) { while(x <= tn) { bit[x] = 0; x += x&(-x); }}void cdq(int l, int r) { if(l == r) { int &d = dp[a[l].id]; d = max(d, 1); return ; } int mid = (l+r)>>1; cdq(mid+1, r); for(int i = mid+1;i <= r; i++) p2[i] = a[i]; for(int i = l; i <= mid; i++) p1[i] = a[i]; sort(p1+l, p1+mid+1); sort(p2+mid+1, p2+r+1); for(int i = mid, j = r;i >= l; i--) { while(j > mid && p2[j].r >= p1[i].r) { update(p2[j].l, dp[p2[j].id]); j--; } int &e = p1[i].id; dp[e] = max(dp[e], query(p1[i].l)+1); } for(int i = mid+1;i <= r; i++) clear(p2[i].l); cdq(l, mid);}void solve() { memset(dp, 0, sizeof(dp)); memset(bit, 0, sizeof(bit)); cdq(1, n); int maxv = -1; for(int i = 1;i <= n; i++) maxv = max(maxv, dp[i]); printf("%d\n", maxv); bool flag = false; int pre = 0; for(int i = 1;i <= n; i++) { if(dp[i] == maxv && (pre == 0||(a[pre].l>=a[i].l&&a[pre].r<=a[i].r))) { if(!flag) { flag = true; printf("%d", i); } else printf(" %d", i); maxv--; pre = i; } } puts("");} int main() { while(scanf("%d", &n) != EOF) { for(int i = 1;i <= n; i++) scanf("%d", &a[i].l); for(int i = 1;i <= n; i++) scanf("%d", &a[i].r); for(int i = 1;i <= n; i++) a[i].id = i; int cnt = 0; for(int i = 1;i <= n; i++) { ls[cnt++] = a[i].l; ls[cnt++] = a[i].r; } sort(ls, ls+cnt); cnt = unique(ls, ls+cnt)-ls; tn = cnt; for(int i = 1;i <= n; i++) { a[i].l = lower_bound(ls, ls+cnt, a[i].l)-ls+1; a[i].r = lower_bound(ls, ls+cnt, a[i].r)-ls+1; } solve(); } return 0;}
0 0
- hdu 5324 Boring Class cdq分治+树状数组+离散化
- hdu 5324 Boring Class(树状数组+笛卡尔树 | 树状数组+cdq分治)
- HDU 5324 Boring Class【cdq分治】
- HDU 5324 Boring Class(CDQ分治)
- Hdu 5324 Boring Class (cdq分治)
- HDU 5324 Boring Class(分治+树状数组)
- HDU 5324 Boring Class 树套树 或 CDQ分治
- HDU 5324 (CDQ分治 树状数组)
- 【cdq分治】 HDOJ 5324 Boring Class
- hdu 5324 Boring Class(15多校第三场1009)(cdq分治)
- HDU 5126 stars cdq分治+树状数组
- hdu 5126 stars ( CDQ分治 + 树状数组)
- HDU 5618 (CDQ分治 树状数组)
- HDU 4742 (CDQ分治 树状数组)
- HDU - 5618 CDQ分治 + 树状数组
- HDU 5324 Boring Class 树状数组套平衡树
- BZOJ1176【CDQ分治】【树状数组】
- HDU 4358 Boring counting(树的遍历+树状数组+离散化+离线处理)
- Ant on a Chessboard
- 敏捷软件开发模型--SCRUM
- iOS 与 Android 生命周期对比
- 机试算法讲解: 第44题 深度优先搜索之素数环问题
- HDU 4986/BC 7B Little Pony and Alohomora Part I
- hdu 5324 Boring Class cdq分治+树状数组+离散化
- Linux 网络编程 调试工具
- [robocup] 3D仿真环境搭建
- PF_INET 和 AF_INET的区别
- 机试算法讲解: 第45题 深度优先搜索之寻找沙特石油存储区
- onvif学习2-soap介绍以及gsoap使用
- 数据同步相关专利
- svn的配置和使用
- 机试算法讲解: 第46题 深度优先搜索之能否逃出魔掌