给定一个序列,每次从序列中找一个长度最大的元素相同的片段,删除它。
如果长度相同,删除最靠左边的那个片段。
问,需要删几次。
用链表处理删除片段。对于删除之后两边又能连成一个片段的那种情况,用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); }