给出一个美丽串,叫你找到下一个比它字典序大的回文串
我们考虑贪心的从后往前替换每一个字母。即对于最后一位(设字母为a),我们把它替换成从a到p的每个字母,如果都不满足美丽串的条件,那么把前一位字母从‘a'替换到p。
问题来了,判断回文串需要O(n)的时间。
分析条件:没有回文串其实就是每个字符不与前两个字符相同。
因为题目给出的是一个美丽串,所以对于当前字符,如果存在大于3长度的回文串,那么这个回文串的字串也一定回文,与题意说的美丽串不符
如图,若替换1号后会形成1234这个回文串,那么2号和3号一定相等,但是原串是个美丽串,即2,3号必不相等,矛盾
然后贪心找出了最高位的数字后,从后往前贪心构造每一位。
即从字典序从小到大选择每一位上填的数,如果可以,则继续下一位

#include<iostream> #include<cstdio> using namespace std; int n,p;char c[100001]; bool check(int i) { if(i==0)return 0; if(i==1)return c[i]==c[i-1]; if(c[i]==c[i-1]||c[i]==c[i-2])return 1; return 0; } void up(int i) { for(;i<n;i++) { for(int j=1;j<=p;j++) { c[i]='a'+j-1; if(!check(i))break; } } } int main() { //freopen("string.in","r",stdin);freopen("string.out","w",stdout); scanf("%d%d%s",&n,&p,c);bool fir=0; int i; for(i=n-1;i>=0;i--) { while(fir==0||(c[i]<='a'+p-1&&check(i))){c[i]++;fir=1;} if(c[i]<='a'+p-1){up(i+1);break;} else fir=0; } if(i==-1)return 0*puts("NO"); for(int i=0;i<n;i++)printf("%c",c[i]); return 0; }
先说结论:答案为n-最长连续上升子序列
显而易见的,每个数最多只会被移动1次
序列中总是存在一些需要移动的和不需要移动的数(下图红色表示需要移动,绿色表示不需要移动)
移动完的序列肯定是长这样的
由于最终移动完的序列有序且连续,所以那些没被移动过的(绿色的)一定是上升且连续的。
所以最小的需要移动的数的个数(红色的)就等于n-最长连续上升子序列
怎么找最长连续上升子序列?
用一个数组wz[]记录每个数出现的位置
从1开始找,如果wz[i+1]>wz[i],那我们就i++,否则计算答案后i++

#include<cstdio> #include<iostream> using namespace std; int wz[100001],a[100001]; int main() { //freopen("sorting.in","r",stdin);freopen("sorting.out","w",stdout); int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);wz[a[i]]=i;} int now=1,ans=0; while(now<=n) { int p=now; while(wz[now+1]>wz[now])now++; ans=max(ans,now-p+1);now++; } printf("%d",n-ans); }
从每个点开始进行一次bfs求出任意两个点间的最短路
对于一条路径a -> b -> c -> d,我们暴力枚举b,c,那么a是所有能到b的点中离b最远的一个点,同理,d是c出发所有能到的点的离c最远的一个点,这些我们都可以预处理出。
但是,这道题没那么简单。四个景点不能重复!
因为a最多只会和c,d重复,d最多只会和a,b重复,所以我们处理出从每个点开始到达的第一,第二,第三远的点以及到每个点的第一,第二,第三远的点,这样一定能包含互不重复的a,b,c,d四个点
时间复杂度O(9n^2)

#include<iostream> #include<cstdio> #include<cstring> using namespace std; int d[2001][2001],que[2101];bool used[2001]; int h[2010],to[10010],next[10010],k=0; int _to[2001][4],from[2001][4],maxt[2001][4],maxf[2001][4]; void ins(int u,int v){next[++k]=h[u];h[u]=k;to[k]=v;} void bfs(int S) { memset(used,0,sizeof(used)); int head=0,tail=0; que[tail++]=S;used[S]=1;d[S][S]=0; while(head<tail) { int u=que[head++]; for(int i=h[u];i;i=next[i]) { int v=to[i];if(!used[v]){used[v]=1;d[S][v]=d[S][u]+1;que[tail++]=v;} } } } int main() { // freopen("travel.in","r",stdin);freopen("travel.out","w",stdout); memset(d,127,sizeof(d));int inf=d[0][0],ans=0; int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);ins(u,v);} for(int i=1;i<=n;i++)bfs(i); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(i==j||d[i][j]==inf)continue; if(d[i][j]>maxf[i][3])maxf[i][3]=d[i][j],from[i][3]=j; if(maxf[i][3]>maxf[i][2])swap(maxf[i][3],maxf[i][2]),swap(from[i][3],from[i][2]); if(maxf[i][2]>maxf[i][1])swap(maxf[i][2],maxf[i][1]),swap(from[i][2],from[i][1]); if(d[i][j]>maxt[j][3])maxt[j][3]=d[i][j],_to[j][3]=i; if(maxt[j][3]>maxt[j][2])swap(maxt[j][3],maxt[j][2]),swap(_to[j][3],_to[j][2]); if(maxt[j][2]>maxt[j][1])swap(maxt[j][2],maxt[j][1]),swap(_to[j][2],_to[j][1]); } int aa,bb,cc,dd; for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) { if(j==k||d[j][k]==inf)continue; for(int i=1;i<=3;i++) { if(_to[j][i]==k||!_to[j][i])continue; for(int l=1;l<=3;l++) { if(from[k][l]==j||!from[k][l]||from[k][l]==_to[j][i])continue; if(d[_to[j][i]][j]+d[j][k]+d[k][from[k][l]]>ans) ans=d[_to[j][i]][j]+d[j][k]+d[k][from[k][l]], aa=_to[j][i],bb=j,cc=k,dd=from[k][l]; } } } printf("%d %d %d %d",aa,bb,cc,dd); return 0; }