Codeforces Round #455 (Div. 2)
D. Colorful Points
题意:给出一个字符串,操作:删除掉与相邻字符不同的字符。问可以进行多少次操作。
tags:乱搞。。好费时间-_-怎么最近的CF都是这么恶心的题???
直接暴力写肯定会T,但可以加个优化: 把连续的相同字符看成一个字符。
然后就是乱搞了,模拟删除与合并。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 2000005; struct Node { int si, sum, pre, next; }p[N]; int cnt, n, sum; char s[N]; void DEL(int x) { p[p[x].next].pre = p[x].pre; p[p[x].pre].next = p[x].next; } int main() { scanf("%s", s+1); n = strlen(s+1); rep(i,1,n-1) { ++sum; if(s[i]!=s[i+1]) { p[++cnt] = (Node){ s[i]-'a', sum, cnt-1, cnt+1 }; sum = 0; } } ++sum; p[++cnt]=(Node){ s[n]-'a', sum, cnt-1, cnt+1 }; int sz=cnt, fir=1, ed=cnt, mi, ans=0; while(sz>1) { mi = min(p[fir].sum, p[ed].sum); for(int i=p[fir].next; i<ed; i=p[i].next) mi = min(mi, (p[i].sum+1)/2); ans += mi; for(int i=p[fir].next; i<ed; i=p[i].next) if((p[i].sum+1)/2==mi) { --sz; DEL(i); } else { p[i].sum -= mi*2; } if(p[fir].sum==mi) { --sz; DEL(fir); fir = p[fir].next; } else { p[fir].sum -= mi; } if(p[ed].sum==mi) { --sz; DEL(ed); ed = p[ed].pre; } else { p[ed].sum -= mi; } for(int i=fir; i<ed; i=p[i].next) { int to = p[i].next; while(p[i].si==p[to].si) { --sz; DEL(to); p[i].sum += p[to].sum; if(to==ed) { ed = i; break; } to = p[i].next; } } } printf("%d ", ans); return 0; }