poj3476 A Game with Colored Balls

每次取最长的最左边一段,可以使用优先队列来实现。而对于每次删除一段则可以使用链表来实现,事实上这里使用数组来模拟链表会有更好的效果。而且最后的评测使用g++会TLE(应该是我代码残了),使用c++可以过。

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

struct Node
{
	char c;
	int pos, len;
	Node(char c, int a, int b)
	{
		this->c = c; pos = a; len = b;
	}
};

bool operator<(const Node& a, const Node& b)
{
	if (a.len == b.len) return a.pos > b.pos;
	else return a.len < b.len;
}

const int MAXN = 1000005;
char s[MAXN];
int pre[MAXN], next[MAXN];
bool vis[MAXN];
priority_queue<Node> q;

int main()
{
	scanf("%s", s);
	int pos = 0, n = strlen(s);
	while (s[pos] != '\0')
	{
		int st = pos, len = 1;
		while (s[++pos] == s[st]) len++;
		q.push(Node(s[st], st, len));
	}
	for (int i = 0; s[i] != '\0'; i++) 
	{
		pre[i] = i - 1;
		next[i] = i + 1;
	}
	memset(vis, false, sizeof(vis));
	
	while (!q.empty())
	{
		Node pnt = q.top(); q.pop();
		if (pnt.len <= 1) break;
		if (vis[pnt.pos]) continue;
		printf("%c", pnt.c);
		int front = pre[pnt.pos], back = pnt.pos;
		for (int i = 0; i < pnt.len; i++, back = next[back])
		{
			vis[back] = true;
			printf(" %d", back + 1);
		}
		printf("\n");
		
		if (front >= 0) next[front] = back;
		if (back < n) pre[back] = front;
		if (front < 0 || back >= n || s[front] != s[back]) continue;
		int len = 2;
		while (pre[front] >= 0 && s[pre[front]] == s[front])
		{
			front = pre[front];
			len++;
		}
		while (next[back] < n && s[back] == s[next[back]])
		{
			back = next[back];
			len++;
		}
		q.push(Node(s[front], front, len));
	}
	return 0;
}


你可能感兴趣的:(poj3476 A Game with Colored Balls)