题目
n个位置,m个操作。操作1,把x个颜色为y的球放到z位置的顶部;操作2,从z位置顶部取出x个球,输出最后一个球的颜色;操作3,把位置u的球倒过来放到位置v顶部。
题解&&思路:
2020CSP-S前的最后一篇题解:
这道题其实是用来自己学习双向链表的,因为之前从没有学过链表(可为什么会写链式前向星),所以借此来学习一下
听大家说,如果学过双向链表,就是一道水题了。
其实双向链表就是要记住一下每个点的前驱与后继,然后对于一类的点要记住它的head与tail即可
知道了这一点,其实这道题就可以直接用双向链表直接搞即可
首先操作1就直接insert,操作2是可以暴力的,操作3因为需要反转,所以这里其实不需要管谁是前驱谁是后继,因为如果每一次都是从最后推前面,因此最后一个点确定,上一个点也确定了,则递推即可
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 3;
int n , m;
struct node{
int num , col , ch[2];//ch记的是前驱或后继
node(){}
node( int N , int C , int CH1 , int CH2 ){
num = N , col = C , ch[0] = CH1 , ch[1] = CH2;
}
}a[MAXN];
int ncnt , head[MAXN] , tail[MAXN];
int main(){
scanf( "%d%d" , &n , &m );
while( m -- ){
int x ,y;
char s[6];scanf( "%s" , s);scanf( "%d%d" , &x , &y );
if( s[2] == 's' ){
int z;scanf( "%d" , &z );
a[++ncnt] = node( x , y , tail[z] , 0 );
if( tail[z] ){
if( a[tail[z]].ch[0] ) a[tail[z]].ch[1] = ncnt;
else a[tail[z]].ch[0] = ncnt;
}
else head[z] = ncnt;
tail[z] = ncnt;
}
else if( s[2] == 't' ){
if( !tail[x] ) continue;
if( tail[y] ){
if( a[tail[y]].ch[0] ) a[tail[y]].ch[1] = tail[x];
else a[tail[y]].ch[0] = tail[x];
if( a[tail[x]].ch[0] ) a[tail[x]].ch[1] = tail[y];
else a[tail[x]].ch[0] = tail[y];
}
else{
head[y] = tail[x];
}
tail[y] = head[x];
head[x] = tail[x] = 0;
}
else{
while( x > a[tail[y]].num ){
x -= a[tail[y]].num;
int last;
if( a[tail[y]].ch[0] ) last = a[tail[y]].ch[0];
else last = a[tail[y]].ch[1];
if( a[last].ch[0] == tail[y] ) a[last].ch[0] = 0;
else a[last].ch[1] = 0;
tail[y] = last;
}
a[tail[y]].num -= x;
printf( "%d\n" , a[tail[y]].col );
}
}
return 0;
}