题目
思路
感谢@太阳星人FxxL 的博客提供了思路。
模拟。唯一需要的优化,就是将连续的同一种颜色压缩成一段。
为什么可以呢?这样一来,每次你 O ( 1 ) \mathcal O(1) O(1) 的访问一个颜色段的时候,至少会被删掉一个点。
于是总复杂度就是点数 O ( n ) \mathcal O(n) O(n) 。
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0' or c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c and c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
inline void writeint(long long x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) writeint(x/10);
putchar((x%10)^48);
}
# define MB template < class T >
MB void getMax(T &a,const T &b){ if(a < b) a = b; }
MB void getMin(T &a,const T &b){ if(b < a) a = b; }
struct Node{
int color, len;
Node* nxt;
Node(int C,int L):color(C),len(L){
nxt = nullptr;
}
};
Node* head;
bool connect(Node* &a){
Node* b = a->nxt;
if(a->color != b->color)
return false;
a->len += b->len, a->nxt = b->nxt;
delete b; return true;
}
char s[1000005];
# define Continue(x) do{ x = x->nxt; }while(false)
int main(){
scanf("%s",s); int n = strlen(s);
Node* now = (head = new Node(s[0],1));
for(int i=1; i<n; ++i){
now->nxt = new Node(s[i],1);
if(not connect(now))
Continue(now);
}
int ans = 0;
while(head != nullptr){
if(head->nxt == nullptr) break;
++ ans, now = head;
while(now->nxt != nullptr){
-- now->nxt->len;
if(now->nxt->nxt != nullptr)
-- now->nxt->len;
if(now->nxt->len <= 0)
Continue(now->nxt);
else Continue(now);
}
-- head->len;
if(head->len <= 0)
Continue(head);
now = head;
while(now != nullptr){
if(now->nxt == nullptr) break;
if(not connect(now)) Continue(now);
}
}
printf("%d\n",ans);
return 0;
}