• Codeforces Round #821 (Div. 2)(A~E)


    A. Consecutive Sum

    最多可以进行k次操作,每次操作可以将两个对k取模相等的下标对应的元素交换位置,问做完这些操作之后每连续的k个数中,最大的和是多少。

    思路:数据范围很小,直接对于所有对k取模相等的数进行比较,取最大的即可。

    AC Code:

    1. #include
    2. typedef long long ll;
    3. const int N=1e5+5;
    4. int t,n,k;
    5. ll a[N];
    6. int main(){
    7. std::ios::sync_with_stdio(false);
    8. std::cin.tie(0);
    9. std::cout.tie(0);
    10. std::cin>>t;
    11. while(t--){
    12. std::cin>>n>>k;
    13. for(int i=1;i<=n;i++){
    14. std::cin>>a[i];
    15. }
    16. ll ans=0;
    17. for(int i=1;i<=k;i++){
    18. ll max=-1;
    19. for(int j=0;i+j*k<=n;j++){
    20. max=std::max(max,a[i+j*k]);
    21. }
    22. ans+=max;
    23. }
    24. std::cout<'\n';
    25. }
    26. return 0;
    27. }

     B. Rule of League

    一列人,从头开始,两两比赛,胜出的人留下,每个人获胜的数量只能是x或y,若存在满足条件的胜负状态则输出任意一种,否则输出-1。

    思路:首先如果一共n个人的获胜次数凑不出来n-1,则输出-1;若可以凑出来,则从头开始赋值即可。

    AC Code:

    1. #include
    2. typedef long long ll;
    3. const int N=1e5+5;
    4. int t;
    5. ll n,x,y;
    6. int main(){
    7. std::ios::sync_with_stdio(false);
    8. std::cin.tie(0);
    9. std::cout.tie(0);
    10. std::cin>>t;
    11. while(t--){
    12. std::cin>>n>>x>>y;
    13. bool flag=false;
    14. int cntx,cnty;
    15. for(int i=0;i
    16. if(x*i+(n-i)*y==n-1){
    17. flag=true;
    18. cntx=i,cnty=n-i;
    19. break;
    20. }
    21. }
    22. if(!flag){
    23. std::cout<<-1<<'\n';
    24. continue;
    25. }
    26. std::vector<int>ans;
    27. int pos=1,cnt=0;
    28. for(int i=1;i<=cntx;i++){
    29. for(int j=1;j<=x;j++){
    30. ans.push_back(pos);
    31. cnt++;
    32. }
    33. pos=cnt+2;
    34. }
    35. for(int i=1;i<=cnty;i++){
    36. for(int j=1;j<=y;j++){
    37. ans.push_back(pos);
    38. cnt++;
    39. }
    40. pos=cnt+2;
    41. }
    42. int len=ans.size();
    43. for(int i=0;i
    44. std::cout<" \n"[i==len-1];
    45. }
    46. }
    47. return 0;
    48. }

    C. Parity Shuffle Sorting

    在一个数组中,可以使用最多n次操作,选择两个数字,若两数加起来为奇数,则将位置靠后的数字改为另一个数;若为偶数,则将位置靠前的数改为前一个数,怎样操作使得在最多n次操作之后使数列变为非递减排序的。

    思路:一般这种题还有什么交互题,都应该去考虑比较极端的情况。这个题可以这样考虑:将第一个数和最后一个数经过一次操作变成一样的,中间的数,如果加起来是奇数的话选第一个数,如果加起来是偶数的话选最后一个数,这样在n-1次操作后将整个序列变成一样的数字,满足条件。(注意1特判,也可能不用?)

    AC Code:

    1. #include
    2. typedef long long ll;
    3. typedef std::pair<int,int>PII;
    4. const int N=1e5+5;
    5. int t,n;
    6. ll a[N];
    7. int main(){
    8. std::ios::sync_with_stdio(false);
    9. std::cin.tie(0);
    10. std::cout.tie(0);
    11. std::cin>>t;
    12. while(t--){
    13. std::cin>>n;
    14. for(int i=1;i<=n;i++){
    15. std::cin>>a[i];
    16. }
    17. if(n==1){
    18. std::cout<<0<<'\n';
    19. continue;
    20. }
    21. std::vectorans;
    22. ans.push_back({1,n});
    23. int pos;
    24. if(a[1]+a[n]&1) pos=a[1];
    25. else pos=a[n];
    26. for(int i=2;i
    27. if(a[i]+pos&1) ans.push_back({1,i});
    28. else ans.push_back({i,n});
    29. }
    30. int len=ans.size();
    31. std::cout<'\n';
    32. for(int i=0;i
    33. std::cout<' '<'\n';
    34. }
    35. }
    36. return 0;
    37. }

     D1. Zero-One (Easy Version)

    给出a和b两个字符串,现对a进行操作,选择两个位置,翻转这两位的数字, 若两位置相邻,则花费为x,否则花费为y,现在求令两个字符串变为相同时的最少花费,若无法变为相同,则输出-1。

    思路:首先当不同的字符是奇数个时,是无法变成相同的字符串,输出-1;因为D1保证了x>=y,所以尽可能不同时修改相邻的位置。当两个相邻且仅有这两个,且x<2*y时,我们必须选择修改相邻的位置;否则,首先修改不相邻的。可以证明除了这种情况外其他的情况都可以使用y解决。

    AC Code:

    1. #include
    2. #define int long long
    3. int t,n,x,y;
    4. std::string a,b;
    5. signed main(){
    6. std::ios::sync_with_stdio(false);
    7. std::cin.tie(0);
    8. std::cout.tie(0);
    9. std::cin>>t;
    10. while(t--){
    11. std::cin>>n>>x>>y;
    12. std::cin>>a>>b;
    13. int cnt=0;
    14. for(int i=0;i
    15. if(a[i]!=b[i]) cnt++;
    16. }
    17. if(cnt&1){
    18. std::cout<<-1<<'\n';
    19. continue;
    20. }
    21. bool flag=false;
    22. for(int i=0;i-1;i++){
    23. if(a[i]!=b[i]&&a[i+1]!=b[i+1]){
    24. if(cnt==2){
    25. flag=true;
    26. break;
    27. }
    28. }
    29. }
    30. if(flag) std::cout<min(x,2*y)<<'\n';
    31. else std::cout<2*y<<'\n';
    32. }
    33. return 0;
    34. }

    os:注意开ll

    D2. Zero-One (Hard Version)

    与D1题意类似,只是不再保证x>=y,且数据范围变成5e3。

    思路:特判的情况与D1差不多,主要就是x

    思路是知乎严格鸽的,orzorzCodeforces Round #821 (Div. 2) D(dp) E(思维) - 知乎 (zhihu.com)

    AC Code:

    1. #include
    2. #define int long long
    3. const int N=5e3+5;
    4. int t,n,x,y;
    5. int f[N][N];
    6. std::string a,b;
    7. std::vector<int>vec;
    8. int getans(int l,int r){
    9. if(l+1==r) return std::min(2*y,x);
    10. else return std::min(y,x*(r-l));
    11. }
    12. int DFS(int l,int r){
    13. if(l>r) return 0;
    14. if(f[l][r]!=-1) return f[l][r];
    15. int res=1e18;
    16. res=std::min(res,DFS(l+1,r-1)+getans(vec[l],vec[r]));
    17. res=std::min(res,DFS(l,r-2)+getans(vec[r-1],vec[r]));
    18. res=std::min(res,DFS(l+2,r)+getans(vec[l],vec[l+1]));
    19. return f[l][r]=res;
    20. }
    21. signed main(){
    22. std::ios::sync_with_stdio(false);
    23. std::cin.tie(0);
    24. std::cout.tie(0);
    25. std::cin>>t;
    26. while(t--){
    27. std::cin>>n>>x>>y;
    28. std::cin>>a>>b;
    29. a=' '+a,b=' '+b;
    30. vec.clear();
    31. for(int i=0;i<=n;i++){
    32. for(int j=0;j<=n;j++)
    33. f[i][j]=-1;
    34. }
    35. for(int i=1;i<=n;i++){
    36. if(a[i]!=b[i])
    37. vec.push_back(i);
    38. }
    39. if(vec.size()%2==1){
    40. std::cout<<-1<<'\n';
    41. continue;
    42. }
    43. if(vec.size()==0){
    44. std::cout<<0<<'\n';
    45. continue;
    46. }
    47. if(vec.size()==2){
    48. if(vec[0]+1==vec[1]) std::cout<min(2*y,x)<<'\n';
    49. else std::cout<min(y,x*(vec[1]-vec[0]))<<'\n';
    50. continue;
    51. }
    52. if(y<=x) std::cout<size()/2*y<<'\n';
    53. else std::cout<<DFS(0,vec.size()-1)<<'\n';
    54. }
    55. return 0;
    56. }

    E. Conveyor

    给出一个无限大的网格,初始时每个网格的方向都是向右的,每一秒都会在(0,0)处放一个箱子,这个箱子会向现在所处网格的方向移动一格,然后网格方向变为向下,即向右和向下交替,q组询问,每次给出一个格子和时间t,判断在时间t时该格子是否有箱子。

    思路:直接计算ts时每一个位置的格子不容易,但是可以计算ts时某一个格子途径了几个箱子,用两个时间的变化量也可以表示。我们定义a[i][j]在ts时,经过了多少箱子。可以知道,a[0][0]=t+1,又因为初始方向为向右,所以该点向右传送了\left \lceil \frac{a[i][j]}{2} \right \rceil向下传送了\left \lfloor \frac{a[i][j]}{2} \right \rfloor,这样计算在两个时间之间的差值,注意,该位置的点在到达该位置之前也至少有i+j的时间。

    AC Code:

    1. #include
    2. #define int long long
    3. typedef long long ll;
    4. const int N=150;
    5. int f[N][N];
    6. int getans(int t,int x,int y){
    7. memset(f,0,sizeof(f));
    8. f[0][0]=std::max(t-(x+y)+1,0ll);
    9. for(int i=0;i<=x;i++){
    10. for(int j=0;j<=y;j++){
    11. f[i+1][j]+=f[i][j]/2;
    12. f[i][j+1]+=f[i][j]-f[i][j]/2;
    13. }
    14. }
    15. return f[x][y];
    16. }
    17. signed main(){
    18. std::ios::sync_with_stdio(false);
    19. std::cin.tie(0);
    20. std::cout.tie(0);
    21. int T;
    22. std::cin>>T;
    23. while(T--){
    24. int t,x,y;
    25. std::cin>>t>>x>>y;
    26. if(getans(t,x,y)-getans(t-1,x,y)>0) std::cout<<"YES"<<'\n';
    27. else std::cout<<"NO"<<'\n';
    28. }
    29. return 0;
    30. }

    os:思维题,感觉确实还好,但是赛时并做不到这里hhhh

  • 相关阅读:
    【无标题】
    ESP 特权隔离机制—案例研究
    【论文复现】——基于逐点前进法的点云数据精简
    ssm+vue的OA办公管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
    解释器模式 行为型模式之五
    JavaScript判断是否为空对象的几种方法
    IDEA插件开发(15)---工具窗口
    【MySQL从入门到精通】【高级篇】(二十一)数据库优化步骤_查看系统性能参数
    spring-boot-starter-actuator实现在UI端查看log
    eclipse配置maven,安装lombok,导入和创建springboot项目
  • 原文地址:https://blog.csdn.net/m0_62289613/article/details/126961192