【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids
给你一个1~n的排列p,n是偶数,每次从中任选一对相邻的数出来,插到排列q的开头,如此循环,问你所能得到的字典序最小的排列q。
我们先确定q开头的两个数q1,q2,q1一定是p的奇数位的最小的数,而q2一定是q1后面最小的偶数位的数,这很显然。
然后记q1,q2在p中的位置分别是L,R,把p分成三段[1,L],[L+1,R-1],[R+1,n],递归处理,当前区间[l,r],每次取的一对的左端点L必然是与当前区间左端点l奇偶性相同的最小的数,而R必然是L右侧与当前区间左端点l奇偶性不同的最小的数。
可以对奇数位和偶数位分别维护一个线段树。
重点是输出答案,我们从前往后构造q,我们发现,所有的数对形成了一个树形结构,比如说[l,r],通过之前我们说的过程,取得数对L,R,则[L,R]之间的数对都必须在L,R输出之后才能输出,我们把这些数对记作[L,R]的子树,递归把树建出来。
然后对我们构造出的这棵树,一开始把所有根的儿子加入堆,我们每次取当前堆里数对左侧的数最小的,输出,然后把它的儿子都加进堆,因为它的所有儿子都“解除了封锁”。如此直到堆空即可。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
priority_queue<int,vector<int>,greater<int> >Heap;
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
int v[200005],first[200005],nex[200005],e;
void AddEdge(int U,int V){v[++e]=V;nex[e]=first[U];first[U]=e;
}
int a[200005],cnt,ma[200005],pai[200005];
int minv[2][100005<<4],n,pos[200005];
void update(int o,int p,int v,int rt,int l,int r)
{if(l==r){minv[o][rt]+=v;return;}int m=(l+r>>1);if(p<=m) update(o,p,v,lson);else update(o,p,v,rson);minv[o][rt]=min(minv[o][rt<<1],minv[o][rt<<1|1]);
}
int query(int o,int ql,int qr,int rt,int l,int r)
{if(ql<=l&&r<=qr) return minv[o][rt];int m=(l+r>>1);int res=2147483647;if(ql<=m) res=min(res,query(o,ql,qr,lson));if(m<qr) res=min(res,query(o,ql,qr,rson));return res;
}
void work(int l,int r,int f){if(l>=r){return;}int L=pos[query(l&1,ma[l],(l%2 == r%2) ? ma[r] : ma[r-1],1,1,n/2)];int R=pos[query((L+1)&1,ma[L+1],((L+1)%2 == r%2) ? ma[r] : ma[r-1],1,1,n/2)];pai[a[L]]=a[R];AddEdge(a[f],a[L]);work(l,L-1,f);work(L+1,R-1,L);work(R+1,r,f);
}
int main(){
// freopen("c.in","r",stdin);scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%d",&a[i]);pos[a[i]]=i;update(i&1,i/2+(i&1),a[i],1,1,n/2);ma[i]=i/2+(i&1);}if(n==2){printf("%d %d\n",a[1],a[2]);return 0;}work(1,n,0);for(int i=first[0];i;i=nex[i]){Heap.push(v[i]);}while(!Heap.empty()){int U=Heap.top(); Heap.pop();cnt+=2;printf("%d %d%c",U,pai[U],cnt==n ? '\n' : ' ');for(int i=first[U];i;i=nex[i]){Heap.push(v[i]);}}return 0;
}
转载于:https://www.cnblogs.com/autsky-jadek/p/7296626.html
【递归】【线段树】【堆】AtCoder Regular Contest 080 E - Young Maids相关推荐
- AtCoder Regular Contest 080
手贱去开了abc,这么无聊.直接arc啊 C - 4-adjacent Time limit : 2sec / Memory limit : 256MB Score : 400 points Prob ...
- AtCoder Regular Contest 061 E - Snuke‘s Subway Trip(建图 + dijkstra最短路 / 0/1bfs / 并查集)
AtCoder Regular Contest 061 E - Snuke's Subway Trip problem 洛谷翻译 my idea 最近一直在做网络流,所以一读这题后,我就想到了最小费用 ...
- NOMURA Programming Contest 2021(AtCoder Regular Contest 121)
文章目录 A - 2nd Greatest Distance B - RGB Matching C - Odd Even Sort D - 1 or 2 E - Directed Tree F - L ...
- AtCoder Regular Contest 065
AtCoder Regular Contest 065 C - Daydream Score : 300300300 points 倒着来就行了,正着来会产生歧义匹配,dreamer,dreamdre ...
- AtCoder Regular Contest 100 D - Equal Cut 思维 + 前缀和
传送门 文章目录 题意: 思路: 题意: 给你一个数组aaa,你要将其分成四份,让这四份中和的最大值−-−最小值最小,输出这个最小值. n≤2e5,ai≤1e9n\le2e5,a_i\le1e9n≤2 ...
- AtCoder Regular Contest 100 E - Or Plus Max Sos dp
传送门 文章目录 题意: 思路: 题意: 给你一个长度为2n2^n2n的数组,让你对于所有的1≤k≤2n−11\le k\le 2^n-11≤k≤2n−1求最大的ai+aj,0≤i<j≤2n−1 ...
- AtCoder题解——AtCoder Regular Contest 107——B - Quadruple
题目相关 题目链接 AtCoder Regular Contest 107 B 题,https://atcoder.jp/contests/arc107/tasks/arc107_b. Problem ...
- AtCoder Regular Contest 120 C - Swaps 2 线段树模拟
传送门 文章目录 题意: 思路: 题意: 给你两个序列a,ba,ba,b,每次可以执行一个操作:将a[i]a[i]a[i]与a[i+1]a[i+1]a[i+1]交换,且让交换后的a[i]+1,a[i+ ...
- Atcoder Regular contest 085F NRE 线段树+DP
题意:给你两个序列,a全部为0,b给出,给出一些区间,可以把a上的这些区间变为全1,要求操作以后两个序列对应位置不相同的个数最小,n<=2e5. 说实话这种区间操作很容易想到线段树,但是我没想到 ...
最新文章
- python基础练习(十)
- 蓝桥备赛第三周 倍增+贪心+素数+约数
- Jquery 禁用元素的所有属性
- Vue父组件使用子组件时,需要携带参数,函数内如何获取子组件给的值
- linux的基础知识——本地套接字
- ExtJS和AngularJS比较
- ffmpeg sws_scale函数详解
- vue与外部html通信,VUE页面实现加载外部HTML方法
- 51nod1255【贪心-栈的应用】
- TIOBE 6 月编程语言排行榜:Java 放缓,C 复兴了!
- LayaAir graphics 矢量绘图之 圆形与扇形
- html页面小宠物代码大全,宠物店网页设计html代码
- 女生可以做软件测试吗?
- obs多推流地址_腾讯推流直播教程OBS下载、安装、使用
- (翻译)9种清晰直观的图标应用原则
- Android/IOS 实现接触NFC自动跳转到App,如果未安装App,则跳转到应用市场
- cisp含金量怎么样?
- pg数据库插件timescale时序库使用记录
- pacemaker+corosync+pg13
- 海康威视工业相机SDK二次开发(VS+Opencv+QT+海康SDK+C++)(一)