CCPC网络赛-2019-Shuffle Card_i++

题意分析: 开始给出一个排列(n个数),然后m次操作,把数x移动到最前面,求最后的排列。

正确代码在最后...

我的思路:

首先想的是数组模拟链表,输入一个就串联前驱和后驱(数组的指向,用下标和值来模拟对应),但是表示较麻烦,果断换思路。

........................................................

接着:想到集合,其次是栈。关键是记录以前输出过的就不再输出了,可用一个数组标记是否输出过。

完整代码:

当时先是TLE超时,是为啥?暂时放在一边。

后面加了换行后WA,说明此题有个坑处:最后不能有多余的换行!

赛后我看了我的程序,应该是集合中元素输出的时候最后多输出了一个空格。现已修改,待验证...

代码:

#include<iostream>
#include<cmath>
#include<stack>
#include<set>
#include<string.h>
using namespace std;
int main(){
set<int> p; //集合
stack<int> s; //栈
int n,m;
scanf("%d %d",&n,&m);
int x;
for(int i=1;i<=n;i++){ //先全部存入集合中
scanf("%d",&x);
p.insert(x);
}
int a[100002]; //标记数组
for(int i=0;i<100002;i++) a[i]=1;
int index=0; //定义集合中要删除的元素个数 栈待会儿需要输出的个数
int size=n; //定义集合中的个数 待会儿需要输出的个数

for(int i=0;i<m;i++){
scanf("%d",&x);
s.push(x); //压栈
if(a[x]==1){
a[x]=0;
p.erase(x);
index++;
size--;
}
}
//cout<<"size="<<size<<endl;
//输出
for(int i=0;i<index;i++){
printf("%d ",s.top());
s.pop();
}

set<int>::iterator it=p.begin();
for(int q=0 ; it!=p.end(); q++ , it++) {
printf("%d",*it);
if(q!=size-1) cout<<" ";
}
return 0;
}

----------------------------------------------------------------------------------------------------------------------------------

看了朋友的解答,我发现了自己走了歪路,因为多用个集合,其实没有必要,直接用数组标记就好了。

不用集合是因为原数据本身有序。

下面是修改后的代码:

#include<iostream>
#include<cmath>
#include<stack>
#include<set>
#include<string.h>
using namespace std;

const int maxx=1e5+10;

int a[maxx];
int main(){
stack<int> s;//栈

int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int x;
int cnt=0; //标记栈待会要输出的个数
while(m--){
cin>>x;
s.push(x);
if(a[x]==-1){
continue;
} else {
cnt++;
}
a[x]=-1; //-1标记为之前已经进栈的元素
}
//输出
for(int i=0;i<cnt;i++){
cout<<s.top();
if(i!=cnt-1) cout<<" ";
s.pop();
}
for(int i=1;i<=n;i++){
if(a[i]!=-1) cout<<" "<<a[i];
}
}

然后发现并不需要分两次输出,再次进行改动:

#include<iostream>
#include<stack>
using namespace std;

const int maxx=1e5+10;
int a[maxx];

int main(){
stack<int> s;
int n,m;
cin>>n>>m;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=n; i>=1; i--) s.push(a[i]);
int x;
while(m--){
cin>>x;
s.push(x);
}
//数据全部进栈
memset(a, false, sizeof(a));
while(!s.empty()){
x=s.top();
s.pop();
if(a[x]==false){
cout<<x;
a[x]=true;
}
}
return 0;
}

这样代码就更加精简,思路更加清晰了。

总之,就是将所有数据全部进栈,然后挨个输出,

因此每次输出后就要将a[x]标记为true,表示这个数已经输出过,后面不用再输出了。