HDU

来源:互联网 发布:ubuntu 14.04 32下载 编辑:程序博客网 时间:2024/05/17 10:24

That's a question. Now Happy (Xi Yangyang) has been caught by Wolffy (Hui Tailang). As Wolffy is busy preparing the big meal, a good idea comes to Happy. He proposes a game that only Wolffy had won, he can eat Happy. Wolffy always believes he is the cleverest one, so they reach a consensus. And they both agree with Wolnie (Hong Tailang) when the referee. A theater will be beat to die by Wolnie's pan. 



The game is defined as follow. 

There are multiple test cases. 

In each case there are R (R < 10) rounds of the game, R is an odd number to guarantee that there must be a winner in the end. 

In each round: There is a pile of n (10 <= n <= 200) Special-cards and m (1 <= m <= 100) piles of Point-card on the table. The Point-card piles are ordered from 1 to m. Wolffy and Happy take turns to get one card from the top of Special-cards pile. Wolffy always takes first in the game. When all the Special-cards have been taken, the round is over and the one with more cards in the hands gains one point. If there is a tie, Wolffy gains one point.(Wolffty and Happy both have 0 point before the game). 

There are 5 kinds of Special-cards besides the Point-card in the game. 

0) Point-card: a card with a point X (1 <= X <= 2000000). 

1) Challenge-card: no matter who takes this card, they both take one card with the maximum point from their own hands. After a comparison, if Happy's card has a larger point, He takes all the Wolffy's in-hands cards, vice versa; If there is a tie no more operation. 

2) Loss-card: the one who takes this card, He must throw a card with the maximum point. 

3) Add-card: a card with P point, the one who gets this card will make the card with maximum point P point larger, i.e. if a Point-card with X point is the maximum, its point will change to X + P. An Add-card can only work on one Point-card. 

4) Exchange-card: a card with Q point. The one who gets this card must change one maximum-point card's point to Q. 

5) Take-card: a card with a integer K, indicates one can get the all the cards of Kth Point-card pile. In one round no two Take-card have the same K. 

You can assume that when one gets the Loss-card, Add-card, Exchange-card, He has at least one card in the hands, when one gets a Challenge-card, they both have at least one card in the hands.


Input 

For each test case, the first line of input is an integer R, indicates the number of rounds: 

Line 2: two integers n indicates the number of Special-cards, m indicates the number of Point-card piles. 

Line 3: a line of m integers. The ith number Pi (1 <= Pi <= 10000)indicates the number cards of ith Point-card pile. 

For the next m lines, ith line contains Pi numbers indicate every Point-card's point of ith Point-card pile. 

The next n lines, in each line, there are five kinds of input, indicate Special-cards by the order of "from top to bottom". 

1) T K: indicates one gets a Take-card, and He can get Kth Point-card pile(1 <= K <= m). 

2) C: indicates one gets a Challenge card. 

3) L: indicates one gets a Loss card. 

4) A P: indicates one gets an Add card with P point (1 <= P <= 30). 

5) E Q: indicates one gets an Exchange card with Q point (1 <= Q <= 2000000).


For each round you should print A:B in a line. A indicate the number of left cards of Wolffy, B indicates the number of left cards of Happy. At the end of game, if Wolffy gains more points, print "Hahaha...I win!!", else print "I will be back!!".


35 33 3 310 11 27 4 124 2 9T 1T 2A 7T 3C6 32 2 21 45 24 2T 2T 1LA 2T 3C5 32 2 21 34 25 2T 2T 1E 3A 1L
9:00:51:2I will be back!!



解题思路:最大堆。这里直接用STL的优先队列+输入挂也能过。但是这是为了学习左偏树用的题。所以还是要自己实现一下左偏树。左偏树很容易理解,具体推荐论文。



左偏树实现 483ms:


#include<iostream>#include<algorithm>#include<stdlib.h>#include<memory.h>#include<queue>using namespace std;const int MAXN=1000100;inline void scanf(int &ret){    char c;    ret = 0;    while ((c = getchar()) < '0' || c > '9');    while (c >= '0' && c <= '9')    {        ret = ret * 10 + (c - '0'), c = getchar();    }}int n;int tot = 0;int v[MAXN], tr[MAXN][2], dist[MAXN], siz[MAXN];int root[MAXN];int l[MAXN], r[MAXN];int merge(int x, int y) {    if (!x || !y) return x + y;    if (v[x] < v[y]) swap(x, y);    tr[x][1] = merge(tr[x][1], y);    siz[x] = siz[tr[x][0]] + siz[tr[x][1]] + 1;    if (dist[tr[x][1]] > dist[tr[x][0]]) swap(tr[x][0], tr[x][1]);    dist[x] = dist[tr[x][1]] + 1;    return x;}int top(int x) {    return v[x];}int size(int x) {    return siz[x];}void pop(int &x) {    x = merge(tr[x][0], tr[x][1]);}int newNode(int x) {    v[++tot] = x;    siz[tot] = 1;    tr[tot][0] = tr[tot][1] = dist[tot] = 0;    return tot;}int num[105];int P[105][10005];int main(){    int R,n,m,temp;    char op[10];    scanf(R);    int YP=0,WP=0;    for(int qqq=0;qqq<R;qqq++){        scanf(n);        scanf(m);        int Y=0;        int W=0;        tot=0;        for(int i=1;i<=m;i++){            scanf(num[i]);        }        for(int i=1;i<=m;i++){            for(int j=0;j<num[i];j++){                scanf(P[i][j]);            }        }        for(int i=1;i<=n;i++){            scanf("%s",op);            if(op[0]=='C'){                int yy=top(Y);                int ww=top(W);                if(yy>ww){                    Y=merge(Y,W);                    W=0;                }                if(ww>yy){                    W=merge(W,Y);                    Y=0;                }            }            if(op[0]=='L'){                if(i%2){                    pop(W);                }                else{                    pop(Y);                }            }            if(op[0]=='A'){                scanf(temp);                if(i%2){                    v[W]=top(W)+temp;                }                else{                    v[Y]=top(Y)+temp;                }            }            if(op[0]=='E'){                scanf(temp);                if(i%2){                    pop(W);                    W=merge(W,newNode(temp));                }                else{                    pop(Y);                    Y=merge(Y,newNode(temp));                }            }            if(op[0]=='T'){                scanf(temp);                if(i%2){                    for(int j=0;j<num[temp];j++)                        W=merge(W,newNode(P[temp][j]));                }                else{                    for(int j=0;j<num[temp];j++)                        Y=merge(Y,newNode(P[temp][j]));                }            }        }        printf("%d:%d\n",size(W),size(Y));        if(size(Y)>size(W))            YP++;        else            WP++;    }    if(YP>WP)        printf("I will be back!!\n");    else        printf("Hahaha...I win!!\n");    return 0;}




优先队列实现 2714ms:

#include<iostream>#include<algorithm>#include<stdlib.h>#include<memory.h>#include<queue>using namespace std;const int MAXN=100010;inline void scanf(int &ret){    char c;    ret = 0;    while ((c = getchar()) < '0' || c > '9');    while (c >= '0' && c <= '9')    {        ret = ret * 10 + (c - '0'), c = getchar();    }}int num[105];int P[105][10005];int main(){    int R,n,m,temp;    char op[10];    scanf(R);    int YP=0,WP=0;    for(int qqq=0;qqq<R;qqq++){        scanf(n);        scanf(m);        priority_queue<int,vector<int>,less<int> > Y;        priority_queue<int,vector<int>,less<int> > W;        for(int i=1;i<=m;i++){            scanf(num[i]);        }        for(int i=1;i<=m;i++){            for(int j=0;j<num[i];j++){                scanf(P[i][j]);            }        }        for(int i=1;i<=n;i++){            scanf("%s",op);            if(op[0]=='C'){                int yy=Y.top();                int ww=W.top();                if(yy>ww){                    while(!W.empty()){                        Y.push(W.top());                        W.pop();                    }                }                if(ww>yy){                    while(!Y.empty()){                        W.push(Y.top());                        Y.pop();                    }                }            }            if(op[0]=='L'){                if(i%2)                    W.pop();                else                    Y.pop();            }            if(op[0]=='A'){                scanf(temp);                if(i%2){                    int yy=W.top()+temp;                    W.pop();                    W.push(yy);                }                else{                    int yy=Y.top()+temp;                    Y.pop();                    Y.push(yy);                }            }            if(op[0]=='E'){                scanf(temp);                if(i%2){                    W.pop();                    W.push(temp);                }                else{                    Y.pop();                    Y.push(temp);                }            }            if(op[0]=='T'){                scanf(temp);                if(i%2){                    for(int i=0;i<num[temp];i++)                        W.push(P[temp][i]);                }                else{                    for(int i=0;i<num[temp];i++)                        Y.push(P[temp][i]);                }            }        }        int yy=Y.size();        int ww=W.size();        printf("%d:%d\n",ww,yy);        if(yy>ww)            YP++;        else            WP++;    }    if(YP>WP)        printf("I will be back!!\n");    else        printf("Hahaha...I win!!\n");    return 0;}




原创粉丝点击