【AtCoder Regular Contest 080E】Young Maids [堆][线段树]
Young Maids
Time Limit: 50 Sec Memory Limit: 512 MB
Description
给定一个排列,每次选出相邻的两个放在队头,要求字典序最小。
Input
第一行一个整数n,第二行n个数表示这个排列。
Output
n个数表示答案。
Sample Input
8
4 6 3 2 8 5 7 1
Sample Output
3 1 2 7 4 6 8 5
HINT
n%2=0,2 <= n <= 2e5
Solution
倒着考虑。
我们维护一个小根堆,堆里面存[l, r, val],表示在区间[l, r]中选择两个元素,第一个元素A的权值为val(保证合法),以val为第一关键字。
那么显然,我们每次选出堆顶进行操作。
显然,若我们取走了A,B(pos[A] < pos[B]),[l,r]就被拆成了 [l,A-1], [A+1,B-1], [B+1,r],我们要保证每一个区间长度都是偶数。
那么只要有,pos[A]%2 == pos[l]%2,pos[B]%2 == pos[r]%2。
又由于我们每次减少两个数,所以这样显然可以保证 pos[B]-pos[A]+1 % 2 == 0。
现在问题就是怎么求出A、B具体是那两个数,显然写个线段树维护一下 某段区间内奇数/偶数位置的min_val和所在的pos即可。
Code
- #include<iostream>
- #include<string>
- #include<algorithm>
- #include<cstdio>
- #include<cstring>
- #include<cstdlib>
- #include<cmath>
- #include<queue>
- using namespace std;
- typedef long long s64;
- const int ONE = ;
- const int INF = ;
- int get()
- {
- int res = , Q = ; char c;
- while( (c = getchar()) < || c > )
- if(c == '-') Q = -;
- if(Q) res = c - ;
- while( (c = getchar()) >= && c <= )
- res = res * + c - ;
- return res * Q;
- }
- int n;
- int a[ONE];
- struct point
- {
- int id, val;
- friend bool operator <(point a, point b)
- {
- if(a.val != b.val) return a.val < b.val;
- return a.id < b.id;
- }
- };
- point res;
- namespace Seg
- {
- struct power {point odd, eve;} Node[ONE * ];
- void Build(int i, int l, int r)
- {
- Node[i].odd.val = Node[i].eve.val = INF;
- if(l == r)
- {
- if(l & ) Node[i].odd = (point){l, a[l]};
- else Node[i].eve = (point){l, a[l]};
- return;
- }
- int mid = l + r >> ;
- Build(i << , l, mid), Build(i << | , mid + , r);
- Node[i].odd = min(Node[i << ].odd, Node[i << | ].odd);
- Node[i].eve = min(Node[i << ].eve, Node[i << | ].eve);
- }
- void Query(int i, int l, int r, int L, int R, int opt)
- {
- if(L <= l && r <= R)
- {
- if(opt == ) res = min(res, Node[i].odd);
- else res = min (res, Node[i].eve);
- return;
- }
- int mid = l + r >> ;
- if(L <= mid) Query(i << , l, mid, L, R, opt);
- if(mid + <= R) Query(i << | , mid + , r, L, R, opt);
- }
- }
- struct power
- {
- int l, r, val;
- bool operator <(power a) const
- {
- if(a.val != val) return a.val < val;
- return a.l < l;
- }
- };
- priority_queue <power> q;
- point Get(int l, int r, int opt)
- {
- res = (point){n + , INF};
- Seg::Query(, , n, l, r, opt);
- return res;
- }
- void Add(int l, int r)
- {
- if(l > r) return;
- q.push((power){l, r, Get(l, r, l % ).val});
- }
- int main()
- {
- n = get();
- for(int i = ; i <= n; i++)
- a[i] = get();
- Seg::Build(, , n);
- Add(, n);
- for(int i = ; i <= n / ; i++)
- {
- power u = q.top(); q.pop();
- point A = Get(u.l, u.r - , u.l % );
- point B = Get(A.id + , u.r, u.r % );
- printf("%d %d ", A.val, B.val);
- Add(u.l, A.id - ), Add(A.id + , B.id - ), Add(B.id + , u.r);
- }
- }
【AtCoder Regular Contest 080E】Young Maids [堆][线段树]的更多相关文章
- Atcoder Grand Contest 023 E - Inversions(线段树+扫描线)
洛谷题面传送门 & Atcoder 题面传送门 毒瘤 jxd 作业-- 首先我们不能直接对所有排列计算贡献对吧,这样复杂度肯定吃不消,因此我们考虑对每两个位置 \(x,y(x<y)\), ...
- 【AtCoder Grand Contest 001F】Wide Swap [线段树][拓扑]
Wide Swap Time Limit: 50 Sec Memory Limit: 512 MB Description Input Output Sample Input 8 3 4 5 7 8 ...
- AtCoder Regular Contest 088 E - Papple Sort(树状数组+结论)
结论:每次把字符丢到最外面最优,用树状数组统计答案,把字符放到最外边后可以当成消失了,直接在树状数组上删掉就好. 感性理解是把字符丢到中间会增加其他字符的移动次数,但是丢到外面不会,所以是正确的. # ...
- AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图
AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图 链接 AtCoder 大意 在数轴上放上n个点,点i可能的位置有\(x_i\)或者\(y_i\ ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
- AtCoder Regular Contest 094 (ARC094) CDE题解
原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...
- AtCoder Regular Contest 092
AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...
- AtCoder Regular Contest 093
AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...
- AtCoder Regular Contest 094
AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...
随机推荐
- vue-cli 安装步骤(转载)
参考资料:Vue2.0 新手完全填坑攻略—从环境搭建到发布 1.Node.js安装 https://nodejs.org/en/download/ 2.安装vue-cli npm install -g ...
- 转载---Atom编辑器常用快捷键
常用快捷键–亲测及翻译 英文 中文 快捷键 功能 New Window 新建界面窗口 Ctrl + Shift + N 如中文意思 New File 新建文件 Ctrl + N 如中文意思 Open ...
- Scrum 项目7.0——第一个Sprint的总结和读后感
总结: 通过这一次的Sprint,我了解了Sprint的整个流程,也学会了编制backlog,也了解了在软件工程中,一个团队的任务是怎么样分配和一个项目是怎么样开展的.从对软件工程的认识只 ...
- LeetCode题解:(114) Flatten Binary Tree to Linked List
题目说明 Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 ...
- apache DBUtils 使用例子demo
转自:http://blog.csdn.net/earbao/article/details/44901061 apache DBUtils是java编程中的数据库操作实用工具,小巧简单实用, 1.对 ...
- VMIC
1. wmic 的简介 wmic -? [全局开关] <命令> 可以使用以下全局开关: /NAMESPACE 别名在其上操作的命名空间的路径. /ROLE 包含别名定义的角色的路径. /N ...
- 创建一个背景透明的UIViewController
有时候想让UIViewController背景透明,让我们可以看到下层的UI,直接设置它的背景颜色为clearColor(),还是有黑色的默认背景在那里.下面是解决该问题的例子: 在storyboar ...
- BZOJ2789 [Poi2012]Letters 【树状数组】
题目链接 BZOJ 题解 如果我们给\(A\)中所有字母按顺序编号,给\(B\)中所有字母编上相同的号码 对于\(B\)中同一种,显然号码应该升序 然后求逆序对即可 #include<algor ...
- VS2010 重命名文件:源文件名和目标文件名相同 的解决方案
想要在“”解决方案资源管理器“”中修改一个已经写好的文件的文件名,如图: 在改了几次后就出现了如图的问题: 然而在“解决方案资源管理器”中并没有看到,于是我打开了工程在磁盘中的位置文件夹: 意外发现了 ...
- python的字符串截取
str = ‘’ :] #截取第一位到第三位的字符 print str[:] #截取字符串的全部字符 :] #截取第七个字符到结尾 ] #截取从头开始到倒数第三个字符之前 ] #截取第三个字符 ] # ...