您的位置:首页 > 其它

HDU 3031 To Be Or Not To Be

2014-07-19 18:14 330 查看
题意:

n堆数字  m个操作  操作是两个人轮流执行  有5种操作  T操作拿一堆数字  C操作两个人比较自己手中最大的数字胜者得到对方的数字  L操作扔掉最大数字  A操作使最大数字加上一个值  E操作是最大数字改变值  两个人按上述规则进行R轮游戏  问每局游戏的比分和最后谁赢

思路:

要么是合并一堆数字  要么从一堆数字里拿最大  很明显这时可并堆的操作  想到使用左偏树

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 2001000

int R,happy,wolf,n,m,tot;
int f[110],root[2],sum[110];
struct node
{
int v,l,r,dis;
}nd
;

int newnode(int x)
{
nd[tot].v=x;
nd[tot].l=0;
nd[tot].r=0;
nd[tot].dis=0;
tot++;
return tot-1;
}

int merge(int x,int y)
{
if(!x) return y;
if(!y) return x;
if(nd[x].v<nd[y].v) swap(x,y);
nd[x].r=merge(nd[x].r,y);
if(nd[nd[x].l].dis<nd[nd[x].r].dis) swap(nd[x].l,nd[x].r);
nd[x].dis=nd[nd[x].r].dis+1;
return x;
}

int pop(int x)
{
int tmp=merge(nd[x].l,nd[x].r);
nd[x].dis=nd[x].l=nd[x].r=0;
return tmp;
}

int main()
{
int i,j,k,num;
char op[10];
while(~scanf("%d",&R))
{
happy=wolf=0;
while(R--)
{
scanf("%d%d",&n,&m);
tot=1;
memset(f,0,sizeof(f));
memset(sum,0,sizeof(sum));
root[0]=root[1]=0;
for(i=1;i<=m;i++) scanf("%d",&sum[i]);
for(i=1;i<=m;i++)
{
for(j=1;j<=sum[i];j++)
{
scanf("%d",&num);
f[i]=merge(f[i],newnode(num));
}
}
for(i=1;i<=n;i++)
{
scanf("%s",op);
if(op[0]=='T')
{
scanf("%d",&k);
root[1&i]=merge(root[1&i],f[k]);
f[k]=0;
sum[(1&i)+105]+=sum[k];
}
else if(op[0]=='C')
{
if(nd[root[0]].v>nd[root[1]].v)
{
root[0]=merge(root[0],root[1]);
sum[105]+=sum[106];
root[1]=0;
sum[106]=0;
}
else if(nd[root[0]].v<nd[root[1]].v)
{
root[1]=merge(root[0],root[1]);
sum[106]+=sum[105];
root[0]=0;
sum[105]=0;
}
}
else if(op[0]=='L')
{
root[1&i]=pop(root[1&i]);
sum[(1&i)+105]--;
}
else if(op[0]=='A')
{
scanf("%d",&k);
nd[root[1&i]].v+=k;
}
else if(op[0]=='E')
{
scanf("%d",&k);
root[1&i]=pop(root[1&i]);
root[1&i]=merge(root[1&i],newnode(k));
}
}
if(sum[105]>sum[106]) happy++;
else wolf++;
printf("%d:%d\n",sum[106],sum[105]);
}
if(happy>wolf) puts("I will be back!!");
else puts("Hahaha...I win!!");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: