您的位置:首页 > 其它

HDU - 3031 To Be Or Not To Be (左偏树模板)

2017-10-24 14:12 543 查看
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!!".

3
5 3
3 3 3
10 11 2
7 4 12
4 2 9
T 1
T 2
A 7
T 3
C
6 3
2 2 2
1 4
5 2
4 2
T 2
T 1
L
A 2
T 3
C
5 3
2 2 2
1 3
4 2
5 2
T 2
T 1
E 3
A 1
L



9:0
0:5
1:2
I 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: