HDU 3031 To Be Or Not To Be(左偏树)

To Be Or Not To Be

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 374    Accepted Submission(s): 149



Problem Description
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
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).
 

Output
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!!".
 

Sample Input
  
  
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

Sample Output
  
  
9:0 0:5 1:2 I will be back!!
 

好久没有写博客了,趁着暑假集训,回来继续奋斗啦!

题意:

题目中说喜羊羊和灰太狼比较所持有的卡片的大小,每张卡片上都有一定的点数,有5种操作,如下:

1) T K: 拿到第 k 堆所有牌

2) C:    喜羊羊和灰太狼手中最大的牌进行比较,赢得一方可以把对方的所有牌全部取过来

3) L:    失去手中最大的一张牌

4) A P: 手中最大的牌点数加上P

5) E Q: 手中最大的牌点数改为Q点

共有R轮比赛,每轮都是双方轮流操作,最后输出输赢即可。

思路:

该题是一道使用左偏树模板的模拟题。

先来介绍一下左偏树模板中每个部分的作用:


合并操作:合并两棵左偏树, (x, y):左偏树编号,输出新左偏树编号

int Merge(int x, int y) {
	if(!x) return y;
	if(!y) return x;
	if(tree[x].val < tree[y].val) swap(x, y);  // 大堆
	tree[x].r = Merge(tree[x].r, y);
	if(tree[tree[x].l].dis < tree[tree[x].r].dis)
		swap(tree[x].l, tree[x].r);
	if(tree[x].r) tree[x].dis = tree[tree[x].r].dis + 1;
	else tree[x].dis = 0;
	return x;
}

删除操作:删除编号为 x 的左偏树的堆顶,返回新的堆顶编号

int Pop(int x) {
	int l = tree[x].l;
	int r = tree[x].r;
	tree[x].l = tree[x].r = tree[x].dis = 0;
	return Merge(l, r);
}

需要注意的是建立节点时,每棵左偏树的编号需要唯一。

知道了这些这题就容易很多了,相见代码。


/*************************************************************************
	> File Name: hdu3031.c
	> Author: Bslin
	> Mail: Baoshenglin1994@gmail.com
	> Created Time: 2014年07月19日 星期六 20时02分14秒
 ************************************************************************/

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define M 1000010

struct node {
	int l, r, dis;
	int val;
} tree[M];
int g[110];

int Merge(int x, int y) {
	if(!x) return y;
	if(!y) return x;
	if(tree[x].val < tree[y].val) swap(x, y);  // 大堆
	tree[x].r = Merge(tree[x].r, y);
	if(tree[tree[x].l].dis < tree[tree[x].r].dis)
		swap(tree[x].l, tree[x].r);
	if(tree[x].r) tree[x].dis = tree[tree[x].r].dis + 1;
	else tree[x].dis = 0;
	return x;
}

int Pop(int x) {
	int l = tree[x].l;
	int r = tree[x].r;
	tree[x].l = tree[x].r = tree[x].dis = 0;
	return Merge(l, r);
}

int main(int argc, char *argv[]) {
	freopen("in.txt", "r", stdin);
	int cas, n, m, i, j;
	int pile[110], p, x, root[2], sum[110], rra, tot;
	char op[5];
	int Happy, Wolffy;
	scanf("%d", &cas);
	Happy = Wolffy = 0;
	while(cas --) {
		scanf("%d%d", &n, &m);
		memset(g, 0, sizeof(g));
		for (i = 1; i <= m; ++i) {
			scanf("%d", &pile[i]);
		}
		tot = 1;
		for (i = 1; i <= m; ++i) {
			for (j = 1; j <= pile[i]; ++j) {
				scanf("%d", &p);
				tree[tot].l = tree[tot].r = tree[tot].dis = 0;
				tree[tot].val = p;
				g[i] = Merge(g[i], tot);
				tot++;
			}
		}
		memset(sum, 0, sizeof(sum));
		root[0] = root[1] = 0;
		for (i = 0; i < n; ++i) {
			scanf("%s", &op);
			if(op[0] == 'T') {
				scanf("%d", &x);
				root[i & 1] = Merge(g[x], root[i & 1]);
				sum[i & 1] += pile[x];
				g[x] = 0;
				pile[x] = 0;
			} else if(op[0] == 'C') {
				if(tree[root[0]].val > tree[root[1]].val) {
					root[0] = Merge(root[0], root[1]);
					sum[0] += sum[1];
					root[1] = 0;
					sum[1] = 0;
				} else {
					root[1] = Merge(root[0], root[1]);
					sum[1] += sum[0];
					root[0] = 0;
					sum[0] = 0;
				}
			} else if(op[0] == 'L') {
				root[i & 1] = Pop(root[i & 1]);
				sum[i & 1] --;
			} else if(op[0] == 'A') {
				scanf("%d", &x);
				tree[root[i & 1]].val += x;
			} else if(op[0] == 'E') {
				scanf("%d", &x);
				rra = Pop(root[i & 1]);
				tree[rra].val = x;
				root[i & 1] = Merge(rra, root[i & 1]);
			}
		}
		printf("%d:%d\n", sum[0], sum[1]);
		if(sum[0] > sum[1]) {
			Wolffy ++;
		} else {
			Happy ++;
		}
	}
	if(Happy > Wolffy) {
		printf("I will be back!!\n");
	} else {
		printf("Hahaha...I win!!\n");
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,HDU1622是一道关于二叉树的题目,要求读入一系列二叉树的节点信息,输出它们的层序遍历结果。如果输入的二叉树不完整或存在重复节点,则输出"not complete"。下面是Java的实现代码: ```java import java.util.LinkedList; import java.util.Queue; import java.util.Scanner; public class Main { static class Node { int val; Node left, right; public Node(int val) { this.val = val; } } public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (sc.hasNext()) { String s = sc.nextLine(); if (s.isEmpty()) { continue; } String[] nodes = s.split("\\s+"); Node root = new Node(Integer.parseInt(nodes[0].substring(1))); Queue<Node> queue = new LinkedList<>(); queue.offer(root); boolean isComplete = true; for (int i = 1; i < nodes.length - 1; i += 2) { Node cur = queue.poll(); if (!nodes[i].equals("()")) { cur.left = new Node(Integer.parseInt(nodes[i].substring(1))); queue.offer(cur.left); } else { isComplete = false; } if (!nodes[i + 1].equals("()")) { cur.right = new Node(Integer.parseInt(nodes[i + 1].substring(0, nodes[i + 1].length() - 1))); queue.offer(cur.right); } else { isComplete = false; } } if (!isComplete) { System.out.println("not complete"); continue; } StringBuilder sb = new StringBuilder(); queue.offer(root); while (!queue.isEmpty()) { Node cur = queue.poll(); sb.append(cur.val).append(" "); if (cur.left != null) { queue.offer(cur.left); } if (cur.right != null) { queue.offer(cur.right); } } System.out.println(sb.toString().trim()); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值