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. 前端开发-css

    css: 是给html标签装饰的,变得更好看. 注释: 单行注释:/*注释内容*/ 多行注释:/* 注释内容 注释内容 注释内容 */ 通常我们在写css代码时也会用注释来划分区域(html代码多,同 ...

  2. 十年老苹果(A1286)强升Catalina及Win10踩坑记

    前言 手头有一台十年老苹果,MacBook Pro,A1286,连视网膜屏都没有,电池也早就衰减以后直接拆掉了(减重). 早些年用得还挺多,后来家里也弄了台式,用得逐渐少了,再后来时不时Windows ...

  3. python 并发专题(五):离散事件仿真(事件循环生成器)

    出租车队运营仿真 创建几辆出租车,每辆车会拉几个乘客,然后回家.出租车首先驶离车库,四处徘徊,寻找乘客:拉到乘客后,行程开始:乘客下车后,继续四处徘徊. 程序解释 程序的输出示例: 创建 3 辆出租车 ...

  4. java 基本语法(十二) 数组(五)Arrays工具类的使用

    1.理解:① 定义在java.util包下.② Arrays:提供了很多操作数组的方法. 2.使用: //1.boolean equals(int[] a,int[] b):判断两个数组是否相等. i ...

  5. css 浮动 定位

    浮动 元素的浮动是指设置了浮动属性的元素会脱离标准普通 流的控制,移动到其父元素中指定位置的过程.  语法: float   . left    . right . none(默认) 注意:    1 ...

  6. 6 个珍藏已久 IDEA 小技巧,这一波全部分享给你!

    每周趣图 产品经理设计体验/用户实际体验 本周就不写技术分析文章了,分享几个珍藏已久的 IDEA 的「骚技巧」,助你快速完成代码. 还等什么?赶紧上车吧...... 先赞后看,养成习惯.微信搜索「程序 ...

  7. Vue JSX、自定义 v-model

    ​博客地址:https://ainyi.com/92 最初用到 JSX,就是做这个博客的时候.iview 表格组件,不支持像 element 那样直接写 html 代码渲染,只能通过 render 函 ...

  8. Go Pentester - HTTP CLIENTS(3)

    Interacting with Metasploit Early-stage Preparation: Setting up your environment - start the Metaspl ...

  9. 集训作业 洛谷P1010 幂次方

    这个…… 这个题看上去有点难的样子. 仔细看看,感觉有点简单.啊,是递归啊,正经的看一看,好像是把一个数分成2的几次方的和. 然后余数和比他小的最大的2的次方数如果不是2的一次方或者2的0次方,就继续 ...

  10. 技术干货:Ceph搭建硬件建议详解

    Ceph是专为在商品硬件上运行而设计的,这使得构建和维护超大规模的数据集群在经济上是可行的.当规划出你的集群硬件时,你需要平衡一些考虑因素,包括故障域和潜在的性能问题.硬件规划应该包括将Ceph守护进 ...