POJ

题目链接:

https://cn.vjudge.net/problem/POJ-3476

题目大意:

一串长度为N的彩球,编号为1-N,每个球的颜色为R,G,B,给出它们的颜色,然后进行如下操作:

每次消除连续颜色最长的最左端的一串,剩下的球如果分成两串,就把左右两串连接起来,输出每次消除的球的颜色及编号。

解题思路:

将球的同一颜色的串压入优先队列中,每次取出最长的串,相同长度的串取最左端的串。

取出来之后,如果将小球分成了两串,如果两端颜色一样可以合并,那就网优先队列中压入新合成的串。每次取出串之后,将串的每一位进行标记,原因是由于没有将原来的两串删除就直接直接加入合并后的串,所以只需要标记一下已经取出,那么后加入的串由于长度长会先出优先队列。算法是正确的。

对于需要输出具体是那些小球,利用pre数组和next数组,pre[i]表示第i个小球前面连着的小球的下标。next则表示后面连着的小球,用这两个数组模拟双端链表,可以输出具体是那些小球。

用C++提交不会超时

 1 //#include<bits/stdc++.h>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn = 1e6 + 10;
 7 typedef long long ll;
 8 struct node
 9 {
10     char c;
11     int pos, len;
12     node(char c, int pos, int len):c(c), pos(pos), len(len){}
13     bool operator <(const node& a)const
14     {
15         return len < a.len || len == a.len && pos > a.pos;//优先队列
16     }
17 };
18 char s[maxn];
19 int pre[maxn], next[maxn];
20 bool vis[maxn];
21 priority_queue<node>q;
22 int main()
23 {
24     scanf("%s", s);
25     int n = strlen(s);
26     for(int i = 0; i < n;)
27     {
28         int st = i, len = 1;
29         while(s[++i] == s[st])len++;
30         //cout<<s[st]<<" "<<st<<" "<<len<<endl;
31         q.push(node(s[st], st, len));
32     }
33     for(int i = 0; i < n; i++)
34     {
35         pre[i] = i - 1, next[i] = i + 1;
36     }
37     memset(vis, 0, sizeof(vis));
38     while(!q.empty())
39     {
40         node now = q.top();
41         q.pop();
42         if(now.len <= 1)break;
43         if(vis[now.pos])continue;
44         printf("%c", now.c);
45         int head = pre[now.pos], tail = now.pos;
46         for(int i = 0; i < now.len; i++, tail = next[tail])
47         {
48             vis[tail] = 1;
49             printf(" %d", tail + 1);
50         }
51         puts("");
52         if(head >= 0)next[head] = tail;
53         if(tail < n)pre[tail] = head;
54         if(head < 0 || tail >= n || s[head] != s[tail])continue;
55 
56         int len = 2;
57         while(pre[head] >= 0 && s[pre[head]] == s[head])
58             head = pre[head], len++;
59         while(next[tail] < n && s[next[tail]] == s[tail])
60             tail = next[tail], len++;
61         q.push(node(s[head], head, len));
62     }
63     return 0;
64 }
原文地址:https://www.cnblogs.com/fzl194/p/9336901.html