[noi.ac_D1T2]sort
https://www.zybuluo.com/ysner/note/1289967
题面
定义"翻转排序":每次操作均为把区间\([l,r]\)中所有数倒过来,即\(swap(a[l],a[r])+swap(a[l+1],a[r-1])+...\)。
每次操作的代价为\(r-l+1\)。
给一个序列\(a\),用"翻转排序"给它排序,并把代价控制在\(2*10^7\)以内。
- \(60pts\) \(n\leq5000\)
- \(ex25pts\) \(a[i]\in\{0,1\}\)
- \(100pts\) \(n\leq5*10^4\)
解析
感觉很符合\(noip\_T2\)难度。。。
\(60pts\)算法
仔细想想,"翻转"这个条件挺恶心的。
可以不"翻转"吗?那就只能交换相邻两个。
把序列扫\(n\)遍,每次只交换序列中相邻两个数。
这样每交换一次对应着消除一个逆序对,复杂度可控。
次数最多为\((n-1)*[(n-1)-1]/2\leq1.25*10^7\)
但是我并不知道这种排序名字叫什么。。。
复杂度\(O(n^2)\)
代码在下一档。
\(85pts\)算法
这个有点搞笑。
直接归并排序就可以了。
每次归并后把左边的\(1\)区间和右边的\(0\)区间并在一起,翻转即可。
复杂度\(O(nlogn)\)
贴上代码。
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define ll long long
#define re register
#define il inline
#define pc(a) putchar(a)
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=1e5+100;
int n,a[N];
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il void wri(re int x)
{
if(x>9) wri(x/10);
pc(x%10+48);
}
il void solve(re int l,re int r)
{
if(l==r) return;
if(l==r-1)
{
if(a[l]>a[r]) swap(a[l],a[r]),printf("%d %d\n",l,r);
return;
}
re int mid=l+r>>1,p1=0,p2=0;
solve(l,mid);solve(mid+1,r);
fp(i,l,mid) if(a[i]==1) {p1=i;break;}
fp(i,mid+1,r) if(a[i]==1) {p2=i;break;}
if(!p1) return;
if(!p2) {printf("%d %d\n",p1,r);reverse(a+p1,a+r+1);return;}
printf("%d %d\n",p1,p2-1);reverse(a+p1,a+p2);
return;
}
int main()
{
n=gi();
fp(i,1,n) a[i]=gi();
if(n<=5000)
{
fp(i,1,n)
{
re int tag=0;
fp(j,1,n-1)
if(a[j]>a[j+1]) tag=1,wri(j),pc(' '),wri(j+1),pc('\n'),swap(a[j],a[j+1]);
if(!tag) break;
}
puts("-1 -1");
return 0;
}
solve(1,n);
puts("-1 -1");
return 0;
}
\(100pts\)算法
蒟蒻其实并不知道快排原理
快排的原理是,在向下分治前,先选取一个基准数,通过归并排序,把该分治区间中的小于等于其的数移到左边,大于其的数移到右边。
归并的过程中可以通过"翻转",把左区间中的大于其的数与右区间中小于等于其的数一次交换完毕。
然后继续向下分治即可。
基准数就是选,该区间中间位置,在排序完后的\(a\)中对应的值。(记得把值离散化)
复杂度\(O(nlog^2n)\)。
很对但是想不到。。。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define re register
#define il inline
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int N=1e5+100;
ll n,a[N],b[N];
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il int Qsort(re int l,re int r,re ll B)
{
if(l==r) return l+(a[l]<=B);
re int mid=l+r>>1,p1=Qsort(l,mid,B),p2=Qsort(mid+1,r,B)-1;
if(p1!=mid+1&&p2!=mid)
{
printf("%d %d\n",p1,p2);
reverse(a+p1,a+p2+1);
}
return p1+(p2-mid);
}
il void solve(re int l,re int r)
{
if(l==r) return;
re int mid=l+r>>1;
Qsort(l,r,b[mid]);
solve(l,mid);solve(mid+1,r);
}
int main()
{
n=gi();
fp(i,1,n) b[i]=a[i]=gi()*n+i;
sort(b+1,b+1+n);
solve(1,n);
puts("-1 -1");
return 0;
}
[noi.ac_D1T2]sort的更多相关文章
- Noip前的大抱佛脚----赛前任务
赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...
- NOI.AC 32 Sort——分治
题目:http://noi.ac/problem/32 从全是0和1的情况入手,可以像线段树一样分治下去,回到本层的时候就是左半部的右边是1,右半部的左边是0,把这两部分换一下就行.代价和时间一样是n ...
- noi.ac day1t3 Sort
传送门 分析 快排的原理是以任意一个数为标准,然后把所有小于它的数换到它的左边,所有大于它的数换到它的右边.我们就使用快排的思路,分治整个区间.对于每个区间以排好序的这个数列的中间位置的值为标准,然后 ...
- noi.ac NOIP2018 全国热身赛 第四场 T2 sort
[题解] 跟51nod 1105差不多. 二分答案求出第L个数和第R个数,check的时候再套一个二分或者用two pointers. 最后枚举ai在b里面二分,找到所有范围内的数,排序后输出. 注意 ...
- [NOI.AC#32]sort 构造
链接 50分做法(只有0,1) 根据归并排序的思想,假设我们现在已经把 \(l\dots mid\) 和 \(mid+1\dots r\) 排好序 只要把左边连续的1和右边连续的0翻转即可 inlin ...
- NOI题库刷题日志 (贪心篇题解)
这段时间在NOI题库上刷了刷题,来写点心得和题解 一.寻找平面上的极大点 2704:寻找平面上的极大点 总时间限制: 1000ms 内存限制: 65536kB 描述 在一个平面上,如果有两个点( ...
- NOI考前乱写
还有13天NOI,把各种乱七八糟的算法都重新过一遍还是比较有必要的... //HDU 5046 Airport //DancingLink #include<iostream> #incl ...
- 数据结构(线段树):NOI 2016 区间
[问题描述] [输入格式] [输出格式] [样例输入] 6 3 3 5 1 2 3 4 2 2 1 5 1 4 [样例输出] 2 [样例说明] [更多样例] 下载 [样例 2 输入输出] 见目录下的 ...
- [NOI 2014]魔法森林
Description 为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士.魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M.初始时小E同学在号节 ...
随机推荐
- day21 05 员工信息表
day21 05 员工信息表 假设有一个员工信息表,里面有每个员工的名字,id,年龄,电话,还有他们所作的工作,而有时候我们并不需要所有的信息,而想根据某些条件,寻找符合条件即可,即筛选, 比如想要筛 ...
- 商业研究(21):活力蛙,足疗O2O,曾经的“中国上门足疗领先品牌”
友情提示:商业研究系列文章,只探讨项目和相关项目的商业本身,不针对任何人和任何组织!!! 2015年,在京东-东家 股权众筹平台,参与投资了足疗O2O项目,活力蛙. 后来由于,股市大跌和资本寒 ...
- Cadence中画原理图的时候器件标号与黄色的参数不同的解决办法
方法是Accessories->Transfer Occ. Prop to Instance->Push Occ. Prop into Instance 将黄色的参数同样应用到源参数. 版 ...
- python之更加抽象 2014-4-6
#更加抽象 12:50pm- 14:50 p112- 1.对象的魔力 多态 如count 在多种数据类型中都可以实现计数的功能 封装 对全局作用域中其他区域隐藏多余信息的原则 继承2.类和类型 创建类 ...
- 【CodeChef】KNGHTMOV(方案数DP)
题意: 考虑一张无限大的方格棋盘.我们有一个“骑士”,它必须从(0,0)格开始,按照如下规则,移动至(X,Y)格:每一步,它只能从(u,v)格移动至(u+Ax,v+Ay)或者(u+Bx,v+By).注 ...
- 【BZOJ4559】成绩比较(组合计数,容斥原理)
题意: G系共有n位同学,M门必修课.这N位同学的编号为0到N-1的整数,其中B神的编号为0号.这M门必修课编号为0到M- 1的整数.一位同学在必修课上可以获得的分数是1到Ui中的一个整数.如果在每门 ...
- 一个Java开发的Python之路----------------(一)
最近开始学习Python了,主要是因为现在在给海航通过JAVA写CMDB运维管理平台,我就是作为唯一一个坐在运维屋里的开发,又当爹,又当妈,前端,后台,测试,设计,需求, 发布,统统一把抓!!在Git ...
- Floyd算法——保存路径——输出路径 HDU1385
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1385 参考 http://blog.csdn.net/shuangde800/article/deta ...
- 洛谷——P1007 独木桥
P1007 独木桥 题目背景 战争已经进入到紧要时间.你是运输小队长,正在率领运输部队向前线运送物资.运输任务像做题一样的无聊.你希望找些刺激,于是命令你的士兵们到前方的一座独木桥上欣赏风景,而你留在 ...
- java设计模式——单例设计模式
/*设计模式:对问题行之有效的解决方式.其实它是一种思想. 1,单例设计模式. 解决的问题:就是可以保证一个类在内存中的对象唯一性. 必须对于多个程序使用同一个配置信息对象时,就需要保证该对象的 ...