Valera and Swaps
题意:
定义 $f(p)$ 表示将 $p$ 序列变换为有序序列最少要交换多少次,给一 $1 \sim n$ 的排列 $a$ ,给一整数 $m$,
求问将 $a$ 最少交换多少次能得到 $p$ ,使得 $f(p) = m$,并将以此交换视作一个两个数字,将交换按顺序排列开
求出字典序最小的交换序列。
解法:
记 $id$ 表示排列 $id(i) = i$
考虑 $f(p)$ 怎么求,可以发现,将原排列视作一个从$p$置换到$id$的置换,则将置换拆分成 $tot$ 个循环后,
最小交换次数就是$\sum_{i=1}^{tot}{cnt_i - 1}$,也就是$n - tot$。
这样考虑交换两个置换的元素,两个置换群会合为一个置换群, $tot$ 变为 $tot-1$。
考虑交换一个置换群内的元素,当前置换群会拆分为两个置换群,$tot$ 变为 $tot+1$。
我们注意到要求交换次数最小,这样两种操作一定不会共存,
这样分类讨论:
1.$n-m < tot$时,我们需要将原先的置换群不断合并,要求字典序最小,
所以我们每次找出含最小元素的置换,将其与含1的置换合并。
2.$n-m = tot$时,不用交换,答案为0
3.$n-m > tot$时,每一次我们只要选择含最小元素的置换,将其中的最小值和次小值交换,并将置换拆开。
总复杂度$O(n^2)$
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector> #define N 3010
#define LL long long using namespace std; int n,m,tot;
int a[N];
bool v[N];
vector<int> cir[N]; int main()
{
while(~scanf("%d",&n))
{
for(int i=;i<=n;i++) scanf("%d",&a[i]);
scanf("%d",&m);
m=n-m;
for(int i=;i<=n;i++) v[i]=;
tot=;
for(int i=;i<=n;i++)
{
if(v[i]) continue;
int tmp=i;
cir[++tot].clear();
while(!v[tmp])
{
v[tmp]=;
cir[tot].push_back(tmp);
tmp=a[tmp];
}
}
if(tot==m) cout<<<<endl;
else if(tot>m)
{
cout<<tot-m<<endl;
for(int Te=;Te<=tot-m;Te++)
{
int t=;
for(int i=;i<=tot;i++)
if(!cir[i].empty() && (!t || cir[i][]<cir[t][]))
t=i;
cout<<cir[][]<<' '<<cir[t][]<<' ';
for(int i=;i<(int)cir[t].size();i++)
cir[].push_back(cir[t][i]);
cir[t].clear();
}
}
else
{
int tott=tot;
cout<<m-tot<<endl;
for(int Te=;Te<=m-tot;Te++)
{
int t=;
for(int i=;i<=tott;i++)
if(cir[i].size()> && (!t || cir[i][]<cir[t][]))
t=i;
int pos=;
for(int i=;i<(int)cir[t].size();i++)
if(cir[t][i]<cir[t][pos])
pos=i;
cout<<cir[t][]<<' '<<cir[t][pos]<<' ';
swap(cir[t][],cir[t][pos]);
cir[++tott].clear();
int cnt=;
for(int i=pos;i<(int)cir[t].size();i++)
cir[tott].push_back(cir[t][i]),cnt++;
while(cnt--) cir[t].pop_back();
}
}
}
return ;
}
Valera and Swaps的更多相关文章
- CodeForces - 441D: Valera and Swaps(置换群)
A permutation p of length n is a sequence of distinct integers p1, p2, ..., pn (1 ≤ pi ≤ n). A permu ...
- Codeforces 441D Valera and Swaps(置换群)
题意: 给定一个1~n的排列(n<=3000),输出字典序最小且次数最少的交换操作,使得操作后的排列可以通过最少m次交换得到排列[1,2,...n] Solution: 可以将排列的对应关系看做 ...
- CF(441D Valera and Swaps)置换群
题意:1-n的一个排列, p2, ..., pn,f(p)的定义是此排列要交换最少的数对能够回到原排列1,2,3,4...n.给一个排列p.要将其变换成f值为m的排列,问至少要交换几个数对,并输出字典 ...
- Codeforces Round 252 (Div. 2)
layout: post title: Codeforces Round 252 (Div. 2) author: "luowentaoaa" catalog: true tags ...
- [codeforces 339]E. Three Swaps
[codeforces 339]E. Three Swaps 试题描述 Xenia the horse breeder has n (n > 1) horses that stand in a ...
- CF 369C . Valera and Elections tree dfs 好题
C. Valera and Elections The city Valera lives in is going to hold elections to the city Parliament ...
- uva331 - Mapping the Swaps
Mapping the Swaps Sorting an array can be done by swapping certain pairs of adjacent entries in the ...
- UVA Mapping the Swaps
题目例如以下: Mapping the Swaps Sorting an array can be done by swapping certain pairs of adjacent entrie ...
- [Codeforces Round #237 (Div. 2)] A. Valera and X
A. Valera and X time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
随机推荐
- Windows 系统 vs2012 MinGW 编译ffmpeg 静态库
Windows系统下 vs2012编译ffmpeg 动态库 前面已经有文章讲述,本文将讲述如果编译生成ffmpeg静态库以方便 在vs2012下调用. 准备工作:安装MinGW环境,修改ffmpeg配 ...
- GTK入门学习:布局练习之计算器
接下来,我们做一个布局练习.例如以下图: 我们用表格布局实现,表格布局參考坐标例如以下: 这里我们用到行编辑控件( GtkEntry ). 行编辑的创建: GtkWidget * gtk_entry_ ...
- c和c++的输入输出
格式输出: printf(格式控制, 输出表列); %d 十进制数 %md m为指定的宽度 若数据位数小于m,则左端补以空格;若大于m,则按实际位数输出 %ld 长整型数据 %mld 指定字段宽 ...
- 后端程序员看前端想死(三)是不是该学点js了
CSS盒子模型 div布局 js 这些都懂一点,但仅仅是懂一点,有时间就学一下咯
- pyquery模块
pyquery 这个模块基本是仿JQuery的形式,也支持CSS选择器语法,因此对于爬虫来说,避免了正则表达式的滥用. 创建对象 from pyquery import PyQuery as pq d ...
- wpf Style也继承(包含内部定义事件)
如何在既定皮肤下为某个style添加内容是我今天碰的问题,皮肤往往是对全局control进行设置的,当然这就无法满足某个个性十足的“另类”了,比如当使用DataGridCheckBoxColumn时, ...
- Cocos2d-JS开发中的一些小技巧
1.获取URL中的请求参数的值----此方法接收参数名 function getQueryString(name) { var reg = new RegExp("(^|&)&quo ...
- java中两字符串比较--compareTo方法
java.lang.String.compareTo() 方法比较两个字符串的字典,比较是基于字符串中的每个字符的Unicode值 String n1 = "1"; String ...
- MongoDB学习笔记(2):数据库操作及CURD初步
MongoDB学习笔记(2):数据库操作及CURD 数据库操作 创建数据库 首先MongoDB中数据库的创建和数据库的切换都是使用命令,USE DATABASE,如果要切换的数据库不存在则会进行创建, ...
- 剑指Offer:合并两个排序的链表【25】
剑指Offer:合并两个排序的链表[25] 题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 题目分析 每次都是比较箭头节点,把小节点连接到已经合 ...