zoukankan      html  css  js  c++  java
  • 【AT5162】[AGC037E] Reversing and Concatenating(贪心)

    点此看题面

    • 给定一个长度为(n)的字符串(s)
    • 执行(k)次操作,每次将(s)的反串(s^R)接到(s)后面,从中任意截取一个长度为(n)的字符串作为新的(s)
    • 求最终能得到的字典序最小的串。
    • (nle5000,kle10^9)

    最小字符贪心

    字典序最小有个显然的贪心,就是让开头最小的字符尽可能多。

    一种情况是原串的末尾就有(t)个最小的字符((tge 1)),那么我们直接翻转原串,然后再以这(2t)个字符为结尾继续翻转,以此类推,最终能得到(t imes 2^k)个最小字符。

    另一种情况是先把原串翻转一次,然后找到某段最小的字符(同样假设为(t)个),最终能得到(t imes 2^{k-1})个最小字符。

    直接暴力枚举这个位置,与已有答案比较更新即可。

    代码:(O(n^2))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 5000
    using namespace std;
    int n,k;char Mn='z',s[2*N+5];
    char ans[N+5],res[N+5];I void Work(char* s,RI k)
    {
    	RI p=n;W(s[p-1]==Mn) --p;RI l=n-p+1;W(l^n&&k) l=min(l<<1,n),--k;//翻转k次
    	RI i;for(i=1;i<=l;++i) res[i]=Mn;for(;i<=n;++i) res[i]=s[p-(i-l)];//l个最小字符,其后的n-l个字符
    	for(i=1;i<=n;++i) if(res[i]^ans[i]) {if(res[i]>ans[i]) return;break;}for(i=1;i<=n;++i) ans[i]=res[i];//和已有答案比较
    }
    int main()
    {
    	RI i;for(scanf("%d%d%s",&n,&k,s+1),i=1;i<=n;++i) Mn=min(Mn,s[i]),ans[i]=s[2*n-i+1]=s[i];
    	if(s[n]==Mn) Work(s,k);if(k) for(i=1;i<=n;++i) s[i+n]==Mn&&(Work(s+i,k-1),0);return puts(ans+1),0;//直接按末尾翻转,翻转一次后枚举位置继续翻转
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    联合主键SQL 联合索引
    SQL 对decimal类型转换为int类型
    SQL获取当前时间月份为两位数
    SQL 对结果集进行分组排序过滤重复数据 ROW_NUMBER
    SQL自动流水号函数
    SQL 索引创建
    .Net三层架构
    2016年你应该学习的语言和框架(转)
    MongoDB学习笔记(转)
    干货分享:让你分分钟学会 javascript 闭包(转)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/AT5162.html
Copyright © 2011-2022 走看看