题解:P6758 [BalticOI 2013] Vim
题意
给定一个长度为 e 全部删掉。
- 删除当前光标上的字符,光标位置不变,花费一次操作
- 把光标向左移,花费一次操作
- 把光标移到下一个任意字符的位置,花费两次操作(并且不能把光标移到
e)
求把字符串中所有的 e 全部删掉所需要的最小操作数。
思路
考虑到光标只能左移,所以考虑移到一段 e 的后一个字符,并称这个字符为关键点,则每个关键点都应该被经过至少一次,然后左移把这一段 e 全部删掉,发现左移的区间不会相交,稍微证明一下,如以下图:
一定不如以下操作:
通过调整法就能把相交的左移区间变成不相交,并且使操作数减小。(以上图仅供感性理解,并不太严谨)
如果我们在给定的字符串
此时如果考虑朴素的 dp,一般只能是
所以这样就可以给出两个 dp 的式子了,一个
先考虑从
第一个
接下来就是从
因为是从
继续向后边走,考虑
第一个是从
最后就是
第一个
#include<bits/stdc++.h>
#define vi vector<int>
#define pb push_back
#define int long long
#define ld long double
#define ull unsigned long long
// #define ll long long
#define LL __int128
// #define faster 1
#define pii pair<int,int>
#define piv pair<int,vi>
#define pic pair<int,char>
#define pdi pair<double,int>
#define mst(x,y) memset(x,y,sizeof x)
#define D(x) cout<<#x<<": "<<x<<endl;
#define DE(x) cout<<#x<<": "<<x<<" ";
#define MAXSIZE 1<<21
#define pl p<<1
#define pr p<<1|1
using namespace std;
constexpr int ksm(int x,int a,int mod){int mul=1;while(a){if(a&1)mul=1ll*mul*x%mod;x=1ll*x*x%mod;a>>=1;}return mul;}
// inline int ksm(int x,int a,int mod){int mul=1;while(a){if(a&1)mul=1ll*mul*x%mod;x=1ll*x*x%mod;a>>=1;}return mul;}
namespace lry{
char buf[MAXSIZE],*p1=buf,*p2=buf;
char pbuf[MAXSIZE],*pp=pbuf;
inline int gc(){
#if faster
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;
#else
return getchar();
#endif
}
inline void pc(const char &c){
#if faster
if(pp-pbuf==MAXSIZE) fwrite(pbuf,1,MAXSIZE,stdout),pp=pbuf;*pp++=c;
#else
putchar(c);
#endif
}
inline bool blank(const char x){return !(x^32)||!(x^10)||!(x^13)||!(x^9);}
inline void read(double &rdx){double t=0;int x=0,s=0,f=1;char c;do c=gc();while(!isdigit(c)&&c!='-'&&c!='.');if (c=='-')f=-1,c=gc();while(isdigit(c)&&c!='.')x=(c^48)+(x<<1)+(x<<3),c=gc();if(c=='.')c=gc();else{rdx=x*f;return;}while(c>='0'&&c<='9')t=t*10+(c^48),s=-~s,c=gc();while(s--)t/=10;rdx=(x+t)*f;}
inline void read(string &x){x="";char a=gc();for(;blank(a)&&(a^-1);a=gc());for(;!blank(a)&&(a^-1);a=gc())x+=a;}
inline void read(char &x){char a=gc();for(;blank(a)&&(a^-1);a=gc());if(!blank(a)&&(a^-1))x=a;}
inline void read(int &x){int ret=0,f=0;char ch=gc();while(!isdigit(ch)){if(ch=='-')f=1;ch=gc();}while(isdigit(ch)){ret=(ret<<1)+(ret<<3)+(ch^48);ch=gc();}x=(f?-ret:ret);}
inline void read(ull &x){ull ret=0;char ch=gc();while(isdigit(ch)){ret=(ret<<1)+(ret<<3)+(ch^48);ch=gc();}x=ret;}
// inline void read(ll &x){ll ret=0,f=0;char ch=gc();while(!isdigit(ch)){if(ch=='-')f=1;ch=gc();}while(isdigit(ch)){ret=(ret<<1)+(ret<<3)+(ch^48);ch=gc();}x=(f?-ret:ret);}
inline void read(LL &x){LL ret=0,f=0;char ch=gc();while(!isdigit(ch)){if(ch=='-')f=1;ch=gc();}while(isdigit(ch)){ret=(ret<<1)+(ret<<3)+(ch^48);ch=gc();}x=(f?-ret:ret);}
template<typename t,typename ...T> inline void read(t &x,T&...y){read(x),read(y...);}
inline void write(int x){if(x<0)pc('-'),x=-x;if(x>9)write(x/10);pc(x%10+48);}
inline void write(char x){pc(x);}
inline void write(ull x){if(x>9)write(x/10);pc(x%10+48);}
// inline void write(ll x){if(x<0)pc('-'),x=-x;if(x>9)write(x/10);pc(x%10+48);}
inline void write(LL x){if(x<0)pc('-'),x=-x;if(x>9)write(x/10);pc(x%10+48);}
inline void write(const char *x){fputs(x,stdout);}
inline void write(const string &x){fputs(x.c_str(),stdout);}
inline void writeln(int x){write(x),pc('\n');}
inline void writetr(int x){write(x),pc(' ');}
inline void writeln(char x){write(x),pc('\n');}
inline void writetr(char x){write(x),pc(' ');}
inline void writeln(ull x){write(x),pc('\n');}
inline void writetr(ull x){write(x),pc(' ');}
// inline void writeln(ll x){write(x),pc('\n');}
// inline void writetr(ll x){write(x),pc(' ');}
inline void writeln(LL x){write(x),pc('\n');}
inline void writetr(LL x){write(x),pc(' ');}
inline void writeln(string x){write(x),pc('\n');}
inline void writetr(string x){write(x),pc(' ');}
template<typename t,typename ...T> inline void write(t x,T...y){write(x),write(y...);}
}
using namespace lry;
constexpr int N=70000+10,M=10+10,QMAX=1000000+10,inf=0x3f3f3f3f3f3f3f3f,base=133,mod=1000000007;
constexpr int base1=233,base2=133,mod1=998244353,mod2=1000000087;
constexpr int dir[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
constexpr int into[4]={2,3,0,1};
constexpr double alpha=0.75,eps=1e-9;
int n,cnt,a[N],t[N],f[N][M],g[N][M][M];
string s;
signed main(){
read(n,s); s=" "+s;
int _n=0;
bool flag=1;
for(int i=1;i<=n;i++){
if(s[i]=='e') cnt++,flag=1;
else t[++_n]=s[i]-'a',a[_n]=flag,flag=0;
}
n=_n;
memset(f,0x3f,sizeof f);
memset(g,0x3f,sizeof g);
f[0][t[1]]=0;
for(int i=1;i<=n;i++){
for(int x=0;x<11;x++){
if(!a[i]&&x!=t[i]) f[i][x]=min(f[i][x],f[i-1][x]);
f[i][x]=min(f[i][x],f[i-1][t[i]]+2);
}
for(int x=0;x<11;x++){
if(x!=t[i]) f[i][x]=min(f[i][x],g[i-1][t[i]][x]);
f[i][x]=min(f[i][x],g[i-1][t[i]][t[i]]+2);
}
for(int x=0;x<11;x++){
for(int y=0;y<11;y++){
if(x!=t[i]) g[i][x][y]=min(g[i][x][y],f[i-1][x]+3);
g[i][x][y]=min(g[i][x][y],f[i-1][t[i]]+5);
}
}
for(int x=0;x<11;x++){
for(int y=0;y<11;y++){
if(x!=t[i]&&y!=t[i]) g[i][x][y]=min(g[i][x][y],g[i-1][x][y]+1);
if(y!=t[i]) g[i][x][y]=min(g[i][x][y],g[i-1][t[i]][y]+3);
if(x!=t[i]) g[i][x][y]=min(g[i][x][y],g[i-1][x][t[i]]+3);
g[i][x][y]=min(g[i][x][y],g[i-1][t[i]][t[i]]+5);
}
}
}
writeln(f[n][10]-2+cnt*2);
#if faster
fwrite(pbuf,1,pp-pbuf,stdout);
pp=pbuf;
#endif
return 0;
}
/*
*/