正题
题目链接:https://ac.nowcoder.com/acm/contest/7611/B
题目大意
nnn个杯子,mmm个操作
- 在第zzz个杯子中依次加入xxx个颜色为yyy的球
- 在第yyy个杯子中取出xxx个球,并询问最后一个拿出的球
- 将第xxx个杯子的球依次拿出放入第yyy个杯子中
解题思路
每次插入操作视为加入一个点,对于没个杯子记录一个顶部和底部的点,然后中间通过若干边连接构成一条链,然后拿出时就从第yyy个杯子的顶部开始搜索查找即可。
然后第三个操作连接两个杯子的顶部然将杯子yyy的顶部设为原来xxx的底部即可。
时间复杂度O(m)O(m)O(m)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10;
struct node{ll to,next;bool w;
}a[N*2];
ll n,m,tot,cnt,ls[N];
ll w[N],num[N],top[N],bot[N];
bool over[N];
void addl(ll x,ll y){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;return;
}
ll ask(ll x,ll fa,ll rest,ll z){if(rest>num[x]){for(ll i=ls[x];i;i=a[i].next){if(a[i].to==fa||over[a[i].to])continue;over[x]=1;return ask(a[i].to,x,rest-num[x],z);}}num[x]-=rest;top[z]=x;return w[x];
}
int main()
{
// freopen("T2_large.in","r",stdin);
// freopen("data.out","w",stdout);scanf("%lld%lld",&n,&m);while(m--){char op[8];ll x,y,z;scanf("%s%lld%lld",op,&x,&y);if(op[2]=='s'){scanf("%lld",&z);w[++cnt]=y;num[cnt]=x;if(!top[z])top[z]=bot[z]=cnt;else addl(cnt,top[z]),top[z]=cnt;}else if(op[2]=='p'){printf("%lld\n",ask(top[y],0,x,y));}else{if(!top[x])continue;if(!top[y]){top[y]=bot[x],bot[y]=top[x];top[x]=bot[x]=0;continue;}addl(top[x],top[y]);top[y]=bot[x];bot[x]=top[x]=0;}}return 0;
}