题解:
左偏树模板题目
每一次合并,删除最大,修改最大
都是基本操作
代码:
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; const int M=105,N=1000005; int T,n,m,p[M],root[M],v1=0,v0=0,c[N][2],dist[N],val[N],cnt; void makeheap(int x,int v) { c[x][0]=c[x][1]=dist[x]=0; val[x]=v; } int merge(int x,int y) { if (!x||!y)return x+y; if (val[x]<val[y])swap(x,y); c[x][1]=merge(c[x][1],y); if (dist[c[x][0]]>dist[c[x][1]])swap(c[x][0],c[x][1]); dist[x]=dist[c[x][1]]+1; return x; } void ps(int &x){x=merge(c[x][0],c[x][1]);} void change(int &x,int v) { int k=merge(c[x][0],c[x][1]); makeheap(x,v); x=merge(x,k); } int main() { scanf("%d",&T); while (T--) { cnt=0; scanf("%d%d",&n,&m); for (int i=1;i<=m;i++)scanf("%d",&p[i]); memset(root,0,sizeof root); for (int i=1;i<=m;i++) for (int j=1,x;j<=p[i];j++) { scanf("%d",&x); makeheap(++cnt,x); root[i]=merge(root[i],cnt); } int x[2],rt[2]; memset(rt,0,sizeof rt); memset(x,0,sizeof x); for (int i=1;i<=n;i++) { char s[2]; int a; scanf("%s",&s); if (s[0]=='T') { scanf("%d",&a); rt[i&1]=merge(rt[i&1],root[a]); x[i&1]+=p[a]; } if (s[0]=='C') { if (val[rt[0]]==val[rt[1]])continue; if (val[rt[0]]>val[rt[1]]) { x[0]+=x[1]; x[1]=0; rt[0]=merge(rt[0],rt[1]); rt[1]=0; } else { x[1]+=x[0]; x[0]=0; rt[1]=merge(rt[1],rt[0]); rt[0]=0; } } if (s[0]=='L') { ps(rt[i&1]); x[i&1]--; } if (s[0]=='A') { scanf("%d",&a); change(rt[i&1],val[rt[i&1]]+a); } if (s[0]=='E') { scanf("%d",&a); change(rt[i&1],a); } } printf("%d:%d ",x[1],x[0]); if (x[1]>=x[0])v1++; else v0++; } if (v1<v0)puts("I will be back!!"); else puts("Hahaha...I win!!"); return 0; }