P4940 Portal2 题解
前言
循环操直到 \(Y\) 号栈为空,把 \(Y\) 号栈的栈顶元素加入到 \(X\) 号栈,删除 \(Y\) 号栈的栈顶元素。
题意
https://www.luogu.com.cn/problem/P4940
题解
前五个操作没什么好说的,直接模拟即可。
对于 SWAP 操作,如果直接模拟会 T。注意到题目只有两个栈,且两次交换后会变回原来的样子,所以可以维护一个变量 \(sp\) 表示是否交换过,每次操作的栈编号都异或上 \(sp\) 即可。
对于 MOVE 操作,同样直接模拟会 T。此时可以使用启发式合并,若 \(y\) 的大小大于 \(x\),可以交换 \(x\) 和 \(y\) 后进行操作。此时两个栈也交换了,所以 \(sp\) 要改变。
但此时会发现,这样操作会使整个栈倒过来。可以维护两个变量 \(rev_0\) 和 \(rev_1\),表示这两个栈是否相反,若反过了就从底部操作,否则从顶部操作。考虑到这不符合 stack 性质,可以换成双端队列 deque。
注意开 long long 。
code
点击查看代码
#include<bits/stdc++.h>
#define CuSO4 cout<<"SUCCESS"<<endl
#define cyq {cout<<"UNSUCCESS"<<endl; continue;}
using namespace std;
typedef long long ll;
deque<ll> stk[2];
bool sp=0,rev[2]={0,0};
void push(ll x,ll n){
if(rev[x]) stk[x].push_back(n);
else stk[x].push_front(n);
}
void pop(ll x){
if(rev[x]) stk[x].pop_back();
else stk[x].pop_front();
}
ll top(ll x){
if(rev[x]) return stk[x].back();
else return stk[x].front();
}
int main(){
ios::sync_with_stdio(false); cin.tie(0);
while(1){
string op; cin>>op;
if(op=="END") break;
else if(op=="PUSH"){
ll x,n; cin>>x>>n;
x^=sp;
push(x,n);
CuSO4;
}else if(op=="POP"){
ll x; cin>>x;
x^=sp;
if(stk[x].empty()) cyq;
pop(x);
CuSO4;
}else if(op=="ADD"){
ll x; cin>>x;
x^=sp;
if(stk[0].empty()||stk[1].empty()) cyq;
ll a=top(0)+top(1);
pop(0); pop(1);
push(x,a);
CuSO4;
}else if(op=="SUB"){
ll x; cin>>x;
x^=sp;
if(stk[0].empty()||stk[1].empty()) cyq;
ll a=abs(top(0)-top(1));
pop(0); pop(1);
push(x,a);
CuSO4;
}else if(op=="DEL"){
ll x; cin>>x;
x^=sp;
while(!stk[x].empty()) pop(x);
CuSO4;
}else if(op=="SWAP"){
sp^=1;
CuSO4;
}else if(op=="MOVE"){
ll x,y; cin>>x>>y;
x^=sp; y^=sp;
bool flag=0;
if(stk[x].size()<stk[y].size()){
swap(x,y);
flag=1;
}
while(!stk[y].empty()){
ll a=top(y); pop(y);
push(x,a);
}
if(flag){
rev[x]^=1;
sp^=1;
}
CuSO4;
}else cyq;
}
CuSO4;
for(ll i=0;i<=1;i++){
if(stk[i^sp].empty()) cout<<"NONE"<<endl;
else{
while(!stk[i^sp].empty()){
cout<<top(i^sp)<<" ";
pop(i^sp);
}
cout<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号