UVA12657 移动盒子 Boxes in a Line 题解(双向链表)
题目链接
题目思路
本质上就是模拟一下双向链表
显然操作4是要做标记的
如果现在是反转那么操作1变为操作2,操作2变为操作1
还有操作3中需要特判相邻的情况
代码
#include<cstdio>
#include<iostream>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
typedef pair<ll,int> pli;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,m;
int l[maxn],r[maxn];
int ca;
void link(int a,int b){
r[a]=b;
l[b]=a;
}
void link(int a,int b,int c){
r[a]=b;
l[b]=a;
r[b]=c;
l[c]=b;
}
signed main(){
while(scanf("%d%d",&n,&m)==2){
for(int i=1;i<=n;i++){
l[i]=i-1;
r[i]=i+1;
}
r[n]=0;
l[0]=1,r[0]=n;
bool flag=1;
for(int i=1,opt,x,y;i<=m;i++){
scanf("%d",&opt);
if(opt==4){
flag=(!flag);
}else{
scanf("%d%d",&x,&y);
if((opt==1||opt==2)&&(!flag)){
opt=3-opt;
}
if(opt==1){
//x放y左边
if(l[y]==x) continue;
link(l[x],r[x]);
link(l[y],x,y);
}else if(opt==2){
//x放y右边
if(r[y]==x) continue;
link(l[x],r[x]);
link(y,x,r[y]);
}else if(opt==3){
if(r[x]!=y&&l[x]!=y){
int lastl=l[y],lastr=r[y];
link(l[x],y,r[x]);
link(lastl,x,lastr);
continue;
}
if(r[y]==x) swap(x,y);
if(r[x]==y){
int lastlx=l[x];
l[r[y]]=x;
r[l[x]]=y;
r[x]=r[y];
l[x]=y;
r[y]=x;
l[y]=lastlx;
}
}
}
}
int beg;// 起点
for(int i=1;i<=n;i++){ //找起点
if(flag&&l[i]==0){
beg=i;
}else if(!flag&&r[i]==0){
beg=i;
}
}
int cnt=1;
ll ans=0;
if(flag){
while(1<=beg&&beg<=n){
if(cnt%2==1) ans+=beg;
beg=r[beg];
cnt++;
}
}else{
while(1<=beg&&beg<=n){
if(cnt%2==1) ans+=beg;
beg=l[beg];
cnt++;
}
}
printf("Case %d: %lld\n",++ca,ans);
}
return 0;
}
不摆烂了,写题