Problem Description
度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣。
初始时有 N 个空的双端队列(编号为 1 到 N ),你要支持度度熊的 Q 次操作。
①1 u w val 在编号为 u 的队列里加入一个权值为 val 的元素。(w=0 表示加在最前面,w=1 表示加在最后面)。
②2 u w 询问编号为 uu 的队列里的某个元素并删除它。( w=0 表示询问并操作最前面的元素,w=1 表示最后面)
③3 u v w 把编号为 v 的队列“接在”编号为 u 的队列的最后面。w=0 表示顺序接(队列 v 的开头和队列 u 的结尾连在一起,队列v 的结尾作为新队列的结尾), w=1 表示逆序接(先将队列 v 翻转,再顺序接在队列 u 后面)。且该操作完成后,队列 v 被清空。
题目大意
给定n个空的队列,
有几种操作,对头或者队尾加入,对头或者队尾删除,查询对头或者队尾,将某两个队列合并,翻转某个队列。
题解
其实嘛,很多操作都是很简单的,
主要问题就是翻转操作,
很容易想到splay的翻转操作,不过也没有这么复杂,直接用链表维护就可以了。
对于每个队列u,处理维护一个正常的链表u以外,对它再多维护一个链表u’,表示u这个队列倒过来的链表。
将队列u和队列v翻转后合并,其实就是将链表u跟链表v’合并,链表v跟链表u’合并,然后清空链表v跟v’。
其他操作都非常简单,只不过代码有点长。
code
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#include <time.h>
#define ll long long
#define N 1500003
#define M 103
#define db double
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
n=0;
ch=G();
while((ch<'0' || ch>'9') && ch!='-')ch=G();
ll w=1;
if(ch=='-')w=-1,ch=G();
while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
n*=w;
}
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}
int n,q,v[N],lst[N],nxt[N],tot;
int cz,u,w,x,y,vl;
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
while(scanf("%d%d",&n,&q)!=EOF)
{
memset(v,0,sizeof(v));
memset(lst,0,sizeof(lst));
memset(nxt,0,sizeof(nxt));
for(int i=1;i<=n;i++)
nxt[i]=n+i,lst[n+i]=i,
nxt[i+n*2]=n*3+i,lst[n*3+i]=i+n*2;
tot=n*4;
for(int k=1;k<=q;k++)
{
read(cz);
if(cz==1)
{
read(u);read(w);read(vl);
if(w==0)
{
v[++tot]=vl;
x=nxt[u];
nxt[tot]=x;
lst[x]=tot;
nxt[u]=tot;
lst[tot]=u;
v[++tot]=vl;
x=lst[u+n*3];
nxt[tot]=u+n*3;
lst[tot]=x;
nxt[x]=tot;
lst[u+n*3]=tot;
}
else
{
v[++tot]=vl;
x=lst[u+n];
nxt[tot]=u+n;
lst[tot]=x;
nxt[x]=tot;
lst[u+n]=tot;
v[++tot]=vl;
x=nxt[u+n*2];
nxt[tot]=x;
lst[x]=tot;
nxt[u+n*2]=tot;
lst[tot]=u+n*2;
}
}
else
if(cz==2)
{
read(u);read(w);
if(nxt[u]==n+u)
{
P('-'),P('1'),P('\n');
continue;
}
if(w==0)
{
x=nxt[u];
write(v[x]),P('\n');
lst[nxt[u]=nxt[x]]=u;
x=lst[u+n*3];
nxt[lst[u+n*3]=lst[x]]=u+n*3;
}
else
{
x=lst[u+n];
write(v[x]),P('\n');
nxt[lst[u+n]=lst[x]]=u+n;
x=nxt[u+n*2];
lst[nxt[u+n*2]=nxt[x]]=u+n*2;
}
}
else
{
read(x);read(y);read(w);
if(x==y)continue;
if(w==0)
{
u=lst[x+n];
lst[nxt[u]=nxt[y]]=u;
u=lst[y+n];
lst[nxt[u]=x+n]=u;
lst[nxt[y]=y+n]=y;
u=nxt[x+n*2];
nxt[lst[u]=lst[y+n*3]]=u;
u=nxt[y+n*2];
nxt[lst[u]=n*2+x]=u;
lst[nxt[y+n*2]=y+n*3]=y+n*2;
}
else
{
u=lst[x+n];
lst[nxt[u]=nxt[y+n*2]]=u;
u=lst[y+n*3];
lst[nxt[u]=x+n]=u;
lst[nxt[y+n*2]=y+n*3]=y+n*2;
u=nxt[x+n*2];
nxt[lst[u]=lst[y+n]]=u;
u=nxt[y];
nxt[lst[u]=n*2+x]=u;
lst[nxt[y]=y+n]=y;
}
}
}
}
return 0;
}