2020/11/03 模拟赛 色球
Description
牛牛有$n$种颜色的彩色小球(编号 $1$ 到$n$),每种颜色的小球他都有无限多个。他 还有$n$个球桶(编号 $1$ 到$n$),球桶的内径与小球直径相当且高度是无限大的,因 此能容纳无限多的小球。他想用这些小球和球桶玩游戏。 一开始这些球桶都是空的,紧接着他会顺次地做$m$个操作,每个操作都是以下 3 类操作中的一个。 1. 把$x$个颜色为$y$的彩色小球放到第$z$个桶的最上面(𝑝𝑢𝑠ℎ 𝑥 𝑦 𝑧); 2. 把最上面的$x$个小球从第 $z$ 个桶内拿出来(𝑝𝑜𝑝 𝑥 𝑧); 3. 把第$u$个桶的所有小球依次从顶部拿出放入第$v$个桶内(𝑝𝑢𝑡 𝑢 𝑣)。 现在他已经确定好了这$m$个操作,但在他开始玩之前,他想知道每次他进行第二 类操作取出的最后一个小球是什么颜色。
Solution
要求维护三个操作:
- 向指定链表中加入元素
- 从指定链表中删除元素
- 两个链表收尾相接
直接链表无脑往上砸
每一次操作时需要判断链表头和链表尾是否存在
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> using namespace std; int n,m,head[400005],tail[400005],tot; char opt[6]; struct Node { int col,num,ch[2]; }node[400005]; inline int read() { int f=1,w=0; char ch=0; while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { w=(w<<1)+(w<<3)+ch-'0'; ch=getchar(); } return f*w; } int main() { n=read(),m=read(); for(int i=1;i<=m;i++) { scanf("%s",opt); if(opt[2]=='s') { int x=read(),y=read(),z=read(); node[++tot]=(Node){y,x,head[z],0}; if(head[z]) { if(node[head[z]].ch[0]) node[head[z]].ch[1]=tot; else node[head[z]].ch[0]=tot; } else { tail[z]=tot; } head[z]=tot; } else if(opt[2]=='p') { int x=read(),z=read(); while(node[head[z]].num<x) { x-=node[head[z]].num; int temp=node[head[z]].ch[0]|node[head[z]].ch[1]; if(temp) { node[temp].ch[0]==head[z]?node[temp].ch[0]=0:node[temp].ch[1]=0; } head[z]=temp; } node[head[z]].num-=x; printf("%d\n",node[head[z]].col); } else { int u=read(),v=read(); if(!head[u]) continue; if(head[v]) { node[head[u]].ch[0]?node[head[u]].ch[1]=head[v]:node[head[u]].ch[0]=head[v]; node[head[v]].ch[0]?node[head[v]].ch[1]=head[u]:node[head[v]].ch[0]=head[u]; } else { tail[v]=head[u]; } head[v]=tail[u]; head[u]=tail[u]=0; } } return 0; }