校省选赛第一场D题TwoDecks题解
2014-04-03 15:10
295 查看
今天晚上第二场比赛,现在还是赛后刷上次的题目,越刷越伤心,发现我赛后一次AC的功力很强大啊!!!(希望今晚变成是赛中一次AC啊!!)
好啦,回归正题。
看题目
two stages.
The first stage is to merge the two decks in such a way that the relative order of the cards from the same deck doesn't change. That is, for any two different cards
i and j in one deck, if card
i lies above card j, then after the merge card
i must also be above card
j.
The second stage is performed on the deck that resulted from the first stage. At this stage, the executed operation is the turning operation. In one turn you can take a few of the top cards, turn all of them, and put them back.
Thus, each of the taken cards gets turned and the order of these cards is reversed. That is, the card that was on the bottom before the turn, will be on top after it.
Your task is to make sure that all the cards are lying face down. Find such an order of merging cards in the first stage and the sequence of turning operations in the second stage, that make all the cards lie face down, and the
number of turns is minimum.
Input
The first input line contains a single integer
n — the number of cards in the first deck
(1 ≤ n ≤ 105).
The second input line contains
n integers, separated by single spaces a1, a2, ..., an
(0 ≤ ai ≤ 1). Value
ai equals 0, if the
i-th card is lying face down, and 1, if the card is lying face up. The cards are given in the order from the topmost one to the bottommost one.
The third input line contains integer
m — the number of cards in the second deck
(1 ≤ m ≤ 105).
The fourth input line contains
m integers, separated by single spaces b1, b2, ..., bm
(0 ≤ bi ≤ 1). Value
bi equals 0, if the
i-th card is lying face down, and 1, if the card is lying face up. The cards are given in the order from the topmost to the bottommost.
Output
In the first line print n + m space-separated integers — the numbers of the cards in the order, in which they will lie after the first stage. List the cards from top to bottom.
The cards from the first deck should match their indexes from
1 to n in the order from top to bottom. The cards from the second deck should match their indexes, increased by
n, that is, numbers from
n + 1 to n + m in the order from top to bottom.
In the second line print a single integer
x — the minimum number of turn operations you need to make all cards in the deck lie face down. In the third line print
x integers: c1, c2, ..., cx
(1 ≤ ci ≤ n + m), each of them represents the number of cards to take from the top of the deck to perform a turn operation. Print the operations in the order, in
which they should be performed.
If there are multiple optimal solutions, print any of them. It is guaranteed that the minimum number of operations doesn't exceed
6·105.
Sample test(s)
Input
Output
Input
Output
同样,先解释一下题目:
有两叠扑克牌,我们要将他们合并在一起,并且让所有扑克牌都朝下
有两个操作:
第一步操作: 将两叠扑克牌合并在一起,但是要保持原来的子顺序,比如
A牌是 正反正 B牌是反正正
1 2 3 4 5 6
合并之后不能是 3 1 2 4 5 6(3跑到1,2上面了!)但是可以是1 2 3 4 5 6 , 4 5 6 1 2 3,1 4 2 5 6 3,……等等,子顺序要保持。
第二步操作: 抽出上面k张牌反转后放回去,直到所有扑克牌都朝下。
比如合并后是 1 0 1 1 1
那么我们抽第一张牌反转后放回去 0 0 1 1 1 ,再抽出前两张,反转放回1 1 1 1 1 ,再5张反转就变成0 0 0 0 0(0 表示向下,1表示向上)
问最少操作次数。
我的思路就是贪心啦!
合并的时候,以第一叠牌的第一张为基准形成情况1 frm,以第二叠牌第一张为基准形成情况2 lat.
之后对于每个情况,如果其中一叠的当前牌是相同状态就直接放进,不然放另外一叠牌的当前牌,力求最相同连续。
这样就得出两个情况对叠后的一副牌啦。
之后就从头开始反转,不同就翻转,最后使得所有的牌都一样状态,此时如果是1状态,就再做一次反转。
这样得出的结果是最优的,这个可以自己想象。
我的代码:
/*******************************************************************************/
/* OS : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux
* Compiler : g++ (GCC) 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
* Encoding : UTF8
* Date : 2014-04-03
* All Rights Reserved by yaolong.
*****************************************************************************/
/* Description: ***************************************************************
*****************************************************************************/
/* Analysis: ******************************************************************
*****************************************************************************/
/*****************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
class Pair
{
public:
int ind,stat;
Pair() {};
Pair & operator =(Pair rhs)
{
this->ind=rhs.ind;
this->stat=rhs.stat;
return *this;
}
};
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
int n,m,i,j,cntf,cntl;
vector<Pair> a,b;
vector<Pair> frm,lat;
int a_i,b_i,f_i,l_i;
while(cin>>n)
{
a.clear();
b.clear();
frm.clear();
lat.clear();
a.resize(n);
for(i=0; i<n; i++)
{
cin>>j;
a[i].ind=i+1;
a[i].stat=j;
}
cin>>m;
b.resize(m);
frm.resize(n+m);
lat.resize(n+m);
for(i=0; i<m; i++)
{
cin>>j;
b[i].ind=n+i+1;
b[i].stat=j;
}
//合并,以a为标准
frm[0]=a[0];
f_i=0;
a_i=1;
b_i=0;
while(f_i<n+m-1)
{
//cout<<"sb"<<f_i<<a_i<<b_i;;
if((a_i<n&&frm[f_i].stat==a[a_i].stat)||b_i==m)
{
f_i++;
frm[f_i]=a[a_i];
a_i++;
}
else
{
f_i++;
frm[f_i]=b[b_i];
b_i++;
}
}
//合并以b为标准
lat[0]=b[0];
l_i=0;
a_i=0;
b_i=1;
while(l_i!=n+m-1)
{
if((b_i<m&&lat[l_i].stat==b[b_i].stat)|| (a_i==n))
{
l_i++;
lat[l_i]=b[b_i];
b_i++;
}
else
{
l_i++;
lat[l_i]=a[a_i];
a_i++;
}
}
/*
for(i=0;i<n+m;i++){
cout<<frm[i].stat<<" ";
}
cout<<endl;
for(i=0;i<n+m;i++){
cout<<lat[i].stat<<" ";
}
cout<<endl;
*/
//对frm测试
cntf=cntl=0;
int stat=frm[0].stat;
for(f_i=1; f_i<n+m; f_i++)
{
if(frm[f_i].stat!=stat)
{
stat=frm[f_i].stat;
cntf++;
}
}
if(stat==1)
{
cntf++;
}
stat=lat[0].stat;
for(l_i=1; l_i<n+m; l_i++)
{
if(lat[l_i].stat!=stat)
{
stat=lat[l_i].stat;
cntl++;
}
}
if(stat==1)
{
cntl++;
}
if(cntl<cntf)
{
for(i=0;i<n+m;i++){
cout<<lat[i].ind<<" ";
}
cout<<endl;
cout<<cntl<<endl;
stat=lat[0].stat;
for(l_i=1; l_i<n+m; l_i++)
{
if(lat[l_i].stat!=stat)
{
stat=lat[l_i].stat;
cout<<l_i<<" ";
}
}
if(stat==1)
{
cout<<l_i;
}
cout<<endl;
}
else
{
for(i=0;i<n+m;i++){
cout<<frm[i].ind<<" ";
}
cout<<endl;
cout<<cntf<<endl;
stat=frm[0].stat;
for(f_i=1; f_i<n+m; f_i++)
{
if(frm[f_i].stat!=stat)
{
stat=frm[f_i].stat;
cout<<f_i<<" ";
}
}
if(stat==1)
{
cout<<f_i<<" ";
}
cout<<endl;
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
好啦,回归正题。
看题目
D. Merging Two Decks
time limit per test
2 seconds
memory limit per test
256 megabytes
input
input.txt
output
output.txt
There are two decks of cards lying on the table in front of you, some cards in these decks lay face up, some of them lay face down. You want to merge them into one deck in which each card is face down. You're going to do it intwo stages.
The first stage is to merge the two decks in such a way that the relative order of the cards from the same deck doesn't change. That is, for any two different cards
i and j in one deck, if card
i lies above card j, then after the merge card
i must also be above card
j.
The second stage is performed on the deck that resulted from the first stage. At this stage, the executed operation is the turning operation. In one turn you can take a few of the top cards, turn all of them, and put them back.
Thus, each of the taken cards gets turned and the order of these cards is reversed. That is, the card that was on the bottom before the turn, will be on top after it.
Your task is to make sure that all the cards are lying face down. Find such an order of merging cards in the first stage and the sequence of turning operations in the second stage, that make all the cards lie face down, and the
number of turns is minimum.
Input
The first input line contains a single integer
n — the number of cards in the first deck
(1 ≤ n ≤ 105).
The second input line contains
n integers, separated by single spaces a1, a2, ..., an
(0 ≤ ai ≤ 1). Value
ai equals 0, if the
i-th card is lying face down, and 1, if the card is lying face up. The cards are given in the order from the topmost one to the bottommost one.
The third input line contains integer
m — the number of cards in the second deck
(1 ≤ m ≤ 105).
The fourth input line contains
m integers, separated by single spaces b1, b2, ..., bm
(0 ≤ bi ≤ 1). Value
bi equals 0, if the
i-th card is lying face down, and 1, if the card is lying face up. The cards are given in the order from the topmost to the bottommost.
Output
In the first line print n + m space-separated integers — the numbers of the cards in the order, in which they will lie after the first stage. List the cards from top to bottom.
The cards from the first deck should match their indexes from
1 to n in the order from top to bottom. The cards from the second deck should match their indexes, increased by
n, that is, numbers from
n + 1 to n + m in the order from top to bottom.
In the second line print a single integer
x — the minimum number of turn operations you need to make all cards in the deck lie face down. In the third line print
x integers: c1, c2, ..., cx
(1 ≤ ci ≤ n + m), each of them represents the number of cards to take from the top of the deck to perform a turn operation. Print the operations in the order, in
which they should be performed.
If there are multiple optimal solutions, print any of them. It is guaranteed that the minimum number of operations doesn't exceed
6·105.
Sample test(s)
Input
3 1 0 1 4 1 1 1 1
Output
1 4 5 6 7 2 3 3 5 6 7
Input
5 1 1 1 1 1 5 0 1 0 1 0
Output
6 1 2 3 4 5 7 8 9 10 4 1 7 8 9
同样,先解释一下题目:
有两叠扑克牌,我们要将他们合并在一起,并且让所有扑克牌都朝下
有两个操作:
第一步操作: 将两叠扑克牌合并在一起,但是要保持原来的子顺序,比如
A牌是 正反正 B牌是反正正
1 2 3 4 5 6
合并之后不能是 3 1 2 4 5 6(3跑到1,2上面了!)但是可以是1 2 3 4 5 6 , 4 5 6 1 2 3,1 4 2 5 6 3,……等等,子顺序要保持。
第二步操作: 抽出上面k张牌反转后放回去,直到所有扑克牌都朝下。
比如合并后是 1 0 1 1 1
那么我们抽第一张牌反转后放回去 0 0 1 1 1 ,再抽出前两张,反转放回1 1 1 1 1 ,再5张反转就变成0 0 0 0 0(0 表示向下,1表示向上)
问最少操作次数。
我的思路就是贪心啦!
合并的时候,以第一叠牌的第一张为基准形成情况1 frm,以第二叠牌第一张为基准形成情况2 lat.
之后对于每个情况,如果其中一叠的当前牌是相同状态就直接放进,不然放另外一叠牌的当前牌,力求最相同连续。
这样就得出两个情况对叠后的一副牌啦。
之后就从头开始反转,不同就翻转,最后使得所有的牌都一样状态,此时如果是1状态,就再做一次反转。
这样得出的结果是最优的,这个可以自己想象。
我的代码:
/*******************************************************************************/
/* OS : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux
* Compiler : g++ (GCC) 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
* Encoding : UTF8
* Date : 2014-04-03
* All Rights Reserved by yaolong.
*****************************************************************************/
/* Description: ***************************************************************
*****************************************************************************/
/* Analysis: ******************************************************************
*****************************************************************************/
/*****************************************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
class Pair
{
public:
int ind,stat;
Pair() {};
Pair & operator =(Pair rhs)
{
this->ind=rhs.ind;
this->stat=rhs.stat;
return *this;
}
};
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
int n,m,i,j,cntf,cntl;
vector<Pair> a,b;
vector<Pair> frm,lat;
int a_i,b_i,f_i,l_i;
while(cin>>n)
{
a.clear();
b.clear();
frm.clear();
lat.clear();
a.resize(n);
for(i=0; i<n; i++)
{
cin>>j;
a[i].ind=i+1;
a[i].stat=j;
}
cin>>m;
b.resize(m);
frm.resize(n+m);
lat.resize(n+m);
for(i=0; i<m; i++)
{
cin>>j;
b[i].ind=n+i+1;
b[i].stat=j;
}
//合并,以a为标准
frm[0]=a[0];
f_i=0;
a_i=1;
b_i=0;
while(f_i<n+m-1)
{
//cout<<"sb"<<f_i<<a_i<<b_i;;
if((a_i<n&&frm[f_i].stat==a[a_i].stat)||b_i==m)
{
f_i++;
frm[f_i]=a[a_i];
a_i++;
}
else
{
f_i++;
frm[f_i]=b[b_i];
b_i++;
}
}
//合并以b为标准
lat[0]=b[0];
l_i=0;
a_i=0;
b_i=1;
while(l_i!=n+m-1)
{
if((b_i<m&&lat[l_i].stat==b[b_i].stat)|| (a_i==n))
{
l_i++;
lat[l_i]=b[b_i];
b_i++;
}
else
{
l_i++;
lat[l_i]=a[a_i];
a_i++;
}
}
/*
for(i=0;i<n+m;i++){
cout<<frm[i].stat<<" ";
}
cout<<endl;
for(i=0;i<n+m;i++){
cout<<lat[i].stat<<" ";
}
cout<<endl;
*/
//对frm测试
cntf=cntl=0;
int stat=frm[0].stat;
for(f_i=1; f_i<n+m; f_i++)
{
if(frm[f_i].stat!=stat)
{
stat=frm[f_i].stat;
cntf++;
}
}
if(stat==1)
{
cntf++;
}
stat=lat[0].stat;
for(l_i=1; l_i<n+m; l_i++)
{
if(lat[l_i].stat!=stat)
{
stat=lat[l_i].stat;
cntl++;
}
}
if(stat==1)
{
cntl++;
}
if(cntl<cntf)
{
for(i=0;i<n+m;i++){
cout<<lat[i].ind<<" ";
}
cout<<endl;
cout<<cntl<<endl;
stat=lat[0].stat;
for(l_i=1; l_i<n+m; l_i++)
{
if(lat[l_i].stat!=stat)
{
stat=lat[l_i].stat;
cout<<l_i<<" ";
}
}
if(stat==1)
{
cout<<l_i;
}
cout<<endl;
}
else
{
for(i=0;i<n+m;i++){
cout<<frm[i].ind<<" ";
}
cout<<endl;
cout<<cntf<<endl;
stat=frm[0].stat;
for(f_i=1; f_i<n+m; f_i++)
{
if(frm[f_i].stat!=stat)
{
stat=frm[f_i].stat;
cout<<f_i<<" ";
}
}
if(stat==1)
{
cout<<f_i<<" ";
}
cout<<endl;
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
相关文章推荐
- 根据map中的value排序map
- Linux设备驱动程序学习(2)-调试技术(补充)
- 一个网友分享的成长经历
- linux如何清除.svn目录
- String s=new String("abc")创建了几个对象?
- 多线程同步说明
- LeetCode | Next Permutation
- Linux设备驱动程序学习(1) -字符设备驱动程序
- 市级人防信息化管理系统登陆上传至服务器
- 身边的逻辑学——简单的真理不简单(3) 当心电视与大众媒体
- 阿里2014校招笔试题(南大)——利用thread和sleep生成字符串的伪随机序列
- CentOS 5.7 将系统语言更换为中文简体
- Linux设备驱动程序学习(2)-调试技术
- linux下进程与线程绑核
- 【cocos2d-x】TexturePacker 使用心得
- 使用Log4j为项目配置日志输出应用详细总结及示例演示.
- C++:文件重定向
- oracle多表联查对结果合并
- 关于tomcat的一些问题
- Spring Annotation 详解