【CODEVS 6384 大米兔学全排列】
·大米兔学习全排列,还有一些逆序对,还有一棵二叉索引树。·
·分析:
首先肯定不是像题目上说的那样,使用next_permutation去完成这道题,因为就算是线性的它也不能承受庞大的排列组合个数。
我们发现这道题可以理解为:建造一个字典序尽量小的序列,满足:①字典序大于原序列②逆序数等于原数列。
怎样才能满足字典序最小呢?首先,我们视作从原数列去修改得到我们的美妙新序列。为了使得新序列字典序尽量靠近原序列(这样才是答案),我们更愿意去修改靠近尾部的部分,这样字典序变换较小。如图:
转换一种思想:我们将要改变原序列的部分规定为原序列的一个后缀,也就是说啊,在这之前的部分我们不作更改,并且改变后这一段的逆序对数目不发生改变。如图啦啦:
那么为什么修改段尽量靠后就一定是答案呢?因为如果靠前一点,如果后面段已经存在解了,那么较长的后缀里构造出来的数列的字典序一定大于等于较短一段。因此,我们需要寻找满足条件的最短后缀,找到以后,对调整它内部元素的顺序,构成答案。
照此思路,必有两个步骤:①找到这个后缀是谁(代码中可以体现为找到后缀左端点)②调整这个区间内的元素顺序,构造答案。
(1)寻找那个梦中的后缀:
不是所有的短后缀都能通过仅修改它内部的元素构造最终答案。我们观赏以下情况,为了方便理解;
我们用柱柱的高度表示每个元素的大小,红色部分表示我们选择这一段后缀来修改,设i为后缀的左端点下标,使用now表示当前数i在区间[i,n]的逆序对数(也就是在这个后缀中关于i的逆序对个数),使用sum表示这个后缀中的总逆序对数[一句提醒:i之前的逆序对我们是不会理睬它的]。我们在草稿纸上乱涂乱画,轻松发现下列情况是不合法的(即仅选择这一段后缀进行修改是不能达到目的的):
【1】单调上升型:
由于后缀区间里的逆序对个数为0,所以我们不可能仅通过调整红色部分内部的元素顺序来保持原来的逆序对总数。这种情况的判断方式为:sum==0。
【2】单调递减型
这种情况的不合法的原因和上文类似。由于逆序对数已经达到了这个区间的唯一最大值:(n-i)*(n-i+1),不可能有其他排列方式。这种情况的判断方式为:sum==(n-i)*(n-i+1)。
【3】垄断型:
此时后缀区间内的所有逆序对都是与i相关的,即sum==now。由于我们要构造字典序更大的一个后缀,那么只能把i位置放上比a[i]大的元素(例如图中的最后一个元素),这个元素一放过来,那么必定会至少造成now+1个逆序对(就是原来i的逆序对和它与i组成的逆序对)。
上文几个自然段已经列出了判断条件,这让我们可以快乐而顺利地从右向左找到第一个合法的后缀i。接下来就要努力构造答案了。
(2)在那个后缀中建造我们的梦:
对于第I位(也就是这个后缀区间的左端点),我们需要保证这一位要换成一个比原来的a[i]大的,但值又尽量小的元素。我们有i的now值可以得到:
在这个后缀区间中,i是第(now+1)小,所以我们为保证新序列字典序尽量小,把i位替换成这个序列第(now+2)大的数(注意,不是整个序列第几大,是这个后缀中的第几大,怎么找到它呢,一会儿说好吗?好)。其实接下来处理完i位后,我们依次处理i+1~n位的方法大体相同:
方法为:我们要尽力使得这个序列字典序最小。啊?这是什么方法啊。欣赏下面这幅图:
我们要坚持让j位元素尽量小的原则(在这之前的部分已经填好数),要让这个数尽量小,也就是它的和剩余区间的逆序对要尽量少,那么在总逆序对保持不变的情况下(这是关键),那么就要使[j+1,n]内部的逆序对尽量多,我们考虑最极端情况,也就是[j+1,n]部分直接呈现单调递减型,那么这样逆序对最大,使得关于j的逆序对最小,使得j位的数最小。
①②整个过程思路如下:
从右向左扫描,找到第一个通过修改能够构成满足条件的字典序最小的新序列的后缀。然后从左向右扫描,保持当前处理的区间[j,n]的逆序对不变,合理分配逆序对的来源,使得关于j的逆序对最少,从而保证最终构造出来的序列的字典序接近原序列。
代码实现算法推荐:今天树状数组半价,推荐您使用这一款。它的这三个操作可以完全胜任这道题:
find函数当然是用来找到第k大的啦。
调用刘汝佳老师经常说的一句话:“本题非常经典,代码实现还有很多细节,请读者认真思考,强烈建议上机实践。(想一想,为什么)”
- #include<stdio.h>
- #include<algorithm>
- #define ll long long
- #define go(i,a,b) for(int i=a;i<=b;i++)
- #define ro(i,a,b) for(int i=a;i>=b;i--)
- using namespace std;
- int n,a[],c[],s,S=;ll now,sum;
- void ADD(int x,int d){while(x<=S)c[x]+=d,x+=x&-x;}
- int Sum(int x){int R=;while(x)R+=c[x],x-=x&-x;return R;}
- int find(int x){s=S;while(s)c[x+s]<now?x+=s,now-=c[x]:,s>>=;return x;}
- int main()
- {
- scanf("%d",&n);while(S<=n)S<<=;
- go(i,,n)scanf("%d",a+i);
- ro(I,n,)
- {
- sum+=(now=Sum(a[I]));ADD(a[I],);
- if(now<sum&&now<n-I&&sum<1ll*(n-I+)*(n-I)/)
- go(i,I,n)i==I?now++:now=max(1ll*,sum-1ll*(n-i)*(n-i-)/),
- sum-=now++,ADD(a[i]=find()+,-),I=;
- }
- go(i,,n)printf("%d ",a[i]);puts("");return ;
- }//Paul_Guderian
这是我们的梦,一个真实的梦,
让每个人和每颗心紧紧相拥。—————汪峰《我们的梦》
【CODEVS 6384 大米兔学全排列】的更多相关文章
- 【NOIP2017 OFO】
·奇怪的标题可能预示着这一篇博文不是讲算法或者分享题目的吧. [一只情绪化的兔子] 今年的11月12日出奇地比去年温暖.两场比赛结束后的我们在临走前去尝试了OFO共享单车,在成都电子科技大学 ...
- 【NOIP2017 OFO(下)】
·我不知道对不对,只是不想让大米兔就这样离开. by tkys_Austin; [另一只情绪化的兔子] 今年的11月12日NOIP提高组, ...
- [noip模拟]食物中毒<暴搜+状压优化>
问题描述 Bqc经过一段时间的研究发现,要解这种毒需要一种特殊的药物.不幸的是,这种药物在 市面上不存在,没有办法Bqc只好亲自制得这种药物.它含有M种化学物质A1,A2,…,AM.现 在Bqc的手上 ...
- 【bzoj4445 scoi2015】小凸想跑步
题目描述 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 nn 边形, nn 个顶点按照逆时针从 00 ∼ n - 1n−1 编号.现在小凸随机站在操场中的某个位置,标 ...
- Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题
除非特别忙,我接下来会尽可能翻译我做的每道CF题的题面! Codeforces 148D 一袋老鼠 Bag of mice | 概率DP 水题 题面 胡小兔和司公子都认为对方是垃圾. 为了决出谁才是垃 ...
- 【Begin】
迫于无奈,我想提高写博速度.我要尽量压缩每道题的题解思路.最终我选择背叛大米兔,但是我支持它.因为它的每一篇博客耗时巨大,精贵的竞赛集训时间经不起它花:可同时精致的博客会带给来浏览的Oier们更多东西 ...
- codevs 1229 数字游戏(可重集的全排列)
传送门 Description Lele 最近上课的时候都很无聊,所以他发明了一个数字游戏来打发时间. 这个游戏是这样的,首先,他拿出几张纸片,分别写上0到9之间的任意数字(可重复写某个数字),然后 ...
- codevs 1294 全排列 next_permuntation
#include<bits/stdc++.h> using namespace std; #define ll long long #define pi (4*atan(1.0)) #de ...
- 全排列 (codevs 1294)题解
[题目描述] 给出一个n, 请输出n的所有全排列(按字典序输出). [样例输入] 3 [样例输出] 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 [解题思路] 听说C++有作 ...
随机推荐
- JavaSE阶段初期的一些问题
对于如下问题1:编译阶段Demo1会报错,Demo2不会报错. class Demo1{ int i; i = 0; } class Demo2{ int i = 0; } 事实上,在java中 ...
- python-装饰器简述
装饰器是什么 用来修饰别的函数的函数就可以称之为装饰器 这种函数的参数一般就是另外一个函数 也就是说,调用这种函数,需要给这种函数传参,且参数是函数 @语法糖 @语法糖一般用来表示装饰器函数 不用@也 ...
- NoSQL&MongoDB
MongoDB: Is NoSQL(技术的实现,并非是一个特定的技术,与RMDS对立):Not only SQL 大数据问题:BigData,eg:同时访问几个页面,代码实现几个页面访问量的大小? F ...
- keycloak管理用户权限
一.在keycloak中定义基础数据 1.realm 如果多个模块使用不同的用户权限,就分realm 如果多个模块共用一套用户权限,就顶一个一个realm 2.每个模块是一个client-app 3. ...
- python入门(4)第一个python程序
python入门(4)第一个python程序 在交互式环境的提示符>>>下,直接输入代码,按回车,就可以立刻得到代码执行结果.现在,试试输入100+200,看看计算结果是不是300: ...
- Homebrew update error not work on OSX
brew update 错误是这样的 chown: /usr/local: Operation not permitted 然后网上osx 10.11, 10.12的解决方法这样的 The probl ...
- 浅谈Web网站的架构演变过程
前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变. 该系统具备的功能: 用户模块:用户注册和管理 商品模块:商品展示和管理 交易模块:创建交易和管理 阶 ...
- 初学Java Web(1)——Web概述
已经很久没有更新博客了,过年忙着吃喝玩乐,就怠惰了一小下下?幸好这学期新开的课程都比较有趣--Java Web和Android.至少对于我自己来说,既充满挑战,又富有趣味. --[1.Web概述]-- ...
- Linux show funny time[ liunx 有趣的东西展示]
Linux show funny time 1.sl 奔跑吧,火车! nick-suo@ubuntu:~$ sudo apt-get install sl 2.telnet 星球大战 nick-suo ...
- https原理通俗了解
摘要:本文尝试一步步还原HTTPS的设计过程,以理解为什么HTTPS最终会是这副模样.但是这并不代表HTTPS的真实设计过程.在阅读本文时,你可以尝试放下已有的对HTTPS的理解,这样更利于" ...