CodeForces

给定一个序列,每次从序列中找一个长度最大的元素相同的片段,删除它。

如果长度相同,删除最靠左边的那个片段。

问,需要删几次。

用链表处理删除片段。对于删除之后两边又能连成一个片段的那种情况,用set记一下合并就好了。

就是如果这个片段被合并成另一片段了,那么优先队列取到这个的时候就直接pop掉。

本来用自定义的结构体实现的。看了大佬的博客,学会了pair的妙用。

pair <a, b>若被排序, a是第一关键字,b是第二关键字。

#include <bits/stdc++.h>
using namespace std;
#define maxn 2000000 + 1000
typedef pair<int, int> Node;
int a[maxn], l[maxn], r[maxn];
int sum[maxn], num[maxn];
set<Node> flag;
priority_queue<Node> q;

int main()
{
        int n, tot = 0;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);

        int tmp = 1;
        for (int i = 1; i <= n; i++)
                if (a[i] == a[i+1]) tmp++;
                    else sum[++tot] = tmp, num[tot] = a[i], tmp = 1;

        for (int i = 1; i <= tot; i++)
                l[i] = i-1, r[i] = i+1, q.push(Node(sum[i], -i));

        int ans = 0;
        while(!q.empty())
        {
                int len = q.top().first, index = -q.top().second;
                q.pop();
                if (flag.count(Node(len, -index))) continue;

                ans++;

                int left = l[index], right = r[index];
                if (left >= 1 && right <= tot && num[left] == num[right])
                {
                        flag.insert(Node(sum[left], -left));
                        flag.insert(Node(sum[right], -right));
                        sum[left] += sum[right];
                        q.push(Node(sum[left], -left));

                        r[left] = r[right];
                        l[r[right]] = left;
                }
                else
                        r[left] = right, l[right] = left;
        }

        printf("%d
", ans);
}
原文地址:https://www.cnblogs.com/ruthank/p/9507361.html