LINK:Permutation



对于这种构造神题 我自然是要补的。为啥就我没想出来哇.

30分还是很好写的 注意8!实际上很小 不需要爆搜 写bfs记录状态即可。至于判断状态是否出现与否 可以开map np一点的做法是利用康拓展开和逆康托展开(还需要hash 没啥用.

但是 经过不断的手玩排列为8的数列容易发现 对于最差的情况 8 7 6 5 4 3 2 1 也最多需要3次。

所以 可以直接去掉bfs的过程 直接三层2^n枚举 开map统计状态量 这样可以做的飞快。算法的名称估计可以叫做为 模拟bfs.

const int MAXN=41000;
int n,T;
int ans;
int a[MAXN],ans1,ans2,ans3;
int s1[MAXN],s2[MAXN],s3[MAXN],p[MAXN],pre2[MAXN],pre3[MAXN];
map<int,int>H[4];
inline void put_(int x,char c){printf("%d%c",x,c);}
inline void put1()
{
put(ans);
if(T)
{
rep(1,n,i)put_(a[i],i==n?'\n':' ');
if(ans1)rep(1,n,i)put_(s1[ans1]/p[i]%10,i==n?'\n':' ');
if(ans2)rep(1,n,i)put_(s2[ans2]/p[i]%10,i==n?'\n':' ');
if(ans3)rep(1,n,i)put_(s3[ans3]/p[i]%10,i==n?'\n':' ');
return;
}
}
int main()
{
//freopen("1.in","r",stdin);
get(n);get(T);
int ss=0,ww=0;p[n]=1;
rep(1,n,i)get(a[i]),ss=ss*10+a[i];
rep(1,n,i)ww=ww*10+i;
fep(n-1,1,i)p[i]=p[i+1]*10;
if(ss==ww){put1();return 0;}
if(n<=8)
{
int maxx=(1<<n)-1;
int id1=0;++ans;
rep(1,maxx,i)
{
int w1=0,w2=0,cnt2=0;
rep(1,n,j)
{
int cc=ss/p[j]%10;
if(i&(1<<(j-1)))w2=w2*10+cc,++cnt2;
else w1=w1*10+cc;
}
w1=w1*p[n-cnt2]+w2;
s1[++id1]=w1;H[1][w1]=1;
if(w1==ww){ans1=id1;put1();return 0;}
}
int id2=0;++ans;
rep(1,maxx,i)
{
rep(1,id1,k)
{
int w1=0,w2=0,cnt2=0;
rep(1,n,j)
{
int cc=s1[k]/p[j]%10;
if(i&(1<<(j-1)))w2=w2*10+cc,++cnt2;
else w1=w1*10+cc;
}
w1=w1*p[n-cnt2]+w2;
if(H[1].find(w1)!=H[1].end()||H[2].find(w1)!=H[2].end())continue;
s2[++id2]=w1;pre2[id2]=k;H[2][w1]=1;if(w1==ww){ans2=id2;ans1=pre2[id2];put1();return 0;}
}
}
int id3=0;++ans;
rep(1,maxx,i)
{
rep(1,id2,k)
{
int w1=0,w2=0,cnt2=0;
rep(1,n,j)
{
int cc=s2[k]/p[j]%10;
if(i&(1<<(j-1)))w2=w2*10+cc,++cnt2;
else w1=w1*10+cc;
}
w1=w1*p[n-cnt2]+w2;
if(H[1].find(w1)!=H[1].end()||H[2].find(w1)!=H[2].end()||H[3].find(w1)!=H[3].end())continue;
s3[++id3]=w1;pre3[id3]=k;H[3][w1]=1;
if(w1==ww)
{ans2=pre3[id3];ans1=pre2[ans2];ans3=id3;put1();return 0;}
}
}
}
return 0;
}

值得注意的是 代码写的过于繁琐 应该写一个函数调用三次 这样可以简便很多.

接下来是考虑正解:观察数据范围 其要求我们最多进行20次这样的操作。

这个下界类似于logn 如何确定下界:每一次都可以将两端进行合并 这样合并的条件两端是递增的 且第一段的最大值<第二段的最小值。

且这两端合并之后数值应该是连续的 不连续就没有意义。

基于数值连续这个思想我们可以设出一个q数组\(q_x\)表示x这个值所处位置。

每次合并两端数值相近的 如果有多段我们可以进行同时合并 所以最多此时为log段数上取整。

还有一种证明方法是 对于q数组 我们把这个数组划分若干段 每一段是连续的极长递增的段。

考虑任意两端 如果每次操作都相同那么他们一定还是无法进行合并 是不合法的。

所以对于任意两端 要求他们的操作序列是不相同的 所以要产生2^k种不同的操作序列才可以还原 答案仍然是logn.

至此 得到答案的下界之后 尝试构造。

构造也很容易了 因为我们知道每次只要合并两段即可 这样最多会合并logn次。

一种比较好写的写法 将每段划分奇偶 下标从0开始.

那么显然 奇数段放1偶数段放0 就可以将两端合并了 下次进行时容易发现下标可以直接/2算出 比暴力标号常数小一倍.

const int MAXN=50010;
int cnt,T,n;
int b[MAXN],a[MAXN],c[MAXN],ql[MAXN],qr[MAXN];
int main()
{
freopen("1.in","r",stdin);
get(n);get(T);
rep(1,n,i)get(a[i]),b[a[i]]=i;
rep(1,n,i)if(b[i]>b[i-1])c[i]=c[i-1];
else c[i]=++cnt;
int w=0;while((1<<w)<cnt+1)++w;
put(w);
if(!T)return 0;
rep(1,n,i)put_(a[i]);puts("");
rep(0,w-1,i)
{
int sl=0,sr=0;
rep(1,n,j)if(!((c[a[j]]>>i)&1))ql[++sl]=a[j];
else qr[++sr]=a[j];
rep(1,sl,j)a[j]=ql[j];
rep(1,sr,j)a[j+sl]=qr[j];
rep(1,n,i)put_(a[i]);puts("");
}
return 0;
}

5.5 省选模拟赛 B Permutation 构造 贪心的更多相关文章

  1. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  2. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  3. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  4. 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)

    一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...

  5. NOI2019省选模拟赛 第五场

    爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...

  6. NOI2019省选模拟赛 第六场

    传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...

  7. 省选模拟赛 arg

    1 arg (arg.cpp/in/out, 1s, 512MB)1.1 Description给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. ...

  8. 5.10 省选模拟赛 拍卖 博弈 dp

    LINK:拍卖 比赛的时候 前面时间浪费的有点多 写这道题的时候 没剩多少时间了. 随便设了一个状态 就开始做了. 果然需要认真的思考.其实 从我的状态的状态转移中可以看出所有的结论. 这里 就不再赘 ...

  9. 省选模拟赛 4.26 T1 dp 线段树优化dp

    LINK:T1 算是一道中档题 考试的时候脑残了 不仅没写优化 连暴力都打挂了. 容易发现一个性质 那就是同一格子不会被两种以上的颜色染.(颜色就三种. 通过这个性质就可以进行dp了.先按照左端点排序 ...

随机推荐

  1. Codeforces 1215D Ticket Game 题解

    Codeforces 1215D Ticket Game 原题 题目 Monocarp and Bicarp live in Berland, where every bus ticket consi ...

  2. 读CSAPP第一章的收获

    这个系列只写了CSAPP第三版对于我的收获. 里面的内容很多,我只写我以前不知道的,然后现在又觉得挺有用的内容. 没有很好的排版,将就看. Amadhl定律:主要观点,想要显著加速整个系统,必须提升全 ...

  3. uni-app网络请求

    对于 GET 方法,会将数据转换为 query string.例如 { name: 'name', age: 18 } 转换后的结果是 name=name&age=18. 对于 POST 方法 ...

  4. 基于tcp/udp协议的套接字通信

    目录 一.套接字分类 二.套接字的工作流程 三.基于tcp协议的套接字 四.基于udp协议的套接字 一.套接字分类 1.基于文件类型的套接字家族:AF_UNIX 2.基于网络类型的套接字家族:AF_I ...

  5. Vue防止按钮重复提交

    参考了:https://www.cnblogs.com/adbg/p/11271237.html 方法:使用全局指令的方式. 一.新建指令 1.我们首先新建一个js文件,例如起名为plugins.js ...

  6. MySQL入门(引擎、数据类型、约束)

    MySQL入门(二) 表的引擎:驱动数据的方式 - 数据库优化 # 概要:引擎是建表规定的,提供给表使用,不是数据库的 # 展示所有引擎 show engines; # innodb(默认): 支持事 ...

  7. MySQL数据库的卸载与安装

    MySQL数据库的卸载与安装 MySQL的完全卸载 因为不知道什么原因,电脑里同时存在两个版本的mysql,所以决定卸载重新安装,但是大家都说MySQL很难清除干净,所以特地查找完全卸载MySQL的方 ...

  8. 使用Xshell的rz命令上传文件失败的解决方法

    使用Xshell的rz命令上传文件失败的解决方法 第一种:在home目录下rz上传文件失败,如下: 原因:当前用户不具备权限解决:用 sudo rz 上传即可成功 第二种:对于文件大的rz上传失败的话 ...

  9. shell专题(九):函数

    9.1 系统函数 1.basename基本语法 basename [string / pathname] [suffix]   (功能描述:basename命令会删掉所有的前缀包括最后一个(‘/’)字 ...

  10. java 基础(二) 搭建Java编译环境(linux系统)

    jdk安装配置 首先下载JDK和JRE,这里你的需要看看你的Linux系统是多少位的,比如我的是64位的:下载JDK并指定到Download目录,JRE同样操作:解压并且配置环境: tar -zxvf ...