• ARC092E Both Sides Merger


    题意

    给你一个长度为 (n) 的序列 (a)

    有两种操作:

    1. 选择一个端点的数,删除

    2. 选择一个非端点的数,将其变为相邻左右两数之和,删去左右两边的数。

    若干次操作后序列只剩下一个数,求最大值,并输出方案。

    (2 leq n leq 1000,|a_i| leq 10^9)

    传送门

    思路

    首先对于二操作,其实一个数所属位置的奇偶性不会改变,奇数位加到奇数位,偶数位加到偶数位,所以最终的最大值中,会由偶数位正数相加和奇数位正数相加产生。

    为什么是正数呢?因为对于负数,中间的我们只需要对它进行二操作,将三个数并成一个,直到两边都是正数为止,负数就消失了。两边的就一直删到需要相应位的正数为止即可。然后我们就得到了一个一个要一个不要的数列,只需要对第二个位置一直做操作二即可。

    注意特判全部都是负数的情况。

    #include <bits/stdc++.h>
    using std::max; 
    const int N=1005;
    long long sum1,sum2;
    int a[N],ans[N],n,cnt,now,l,r,t;
    int main(){
    	scanf("%d",&n);
    	for (int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		if (i&1) sum1+=max(a[i],0);
    		else sum2+=max(a[i],0);
    	}
    	if (sum1==0 && sum2==0){
    		int mx=1;
    		for (int i=1;i<=n;i++) if (a[i]>a[mx]) mx=i;
    		printf("%d
    %d
    ",a[mx],n-1);
    		for (int i=n;i>mx;i--) printf("%d
    ",i);
    		for (int i=1;i<mx;i++) printf("%d
    ",1);
    		return 0; 
    	}
    	if (sum1>sum2){
    		t=1;
    		printf("%lld
    ",sum1);	
    	} else t=0,printf("%lld
    ",sum2);
    	int i=n;
    	for (;(i%2)!=t || a[i]<0;i--) ans[++cnt]=i;
    	r=i;
    	i=1;
    	for (;(i%2)!=t || a[i]<0;i++) ans[++cnt]=1;
    	l=i;
    	for (i=l;i<=r;i+=2) 
    		if (a[i]<0 && (i%2)==t) ans[++cnt]=now*2+1;
    		else now++;
    	for (int i=1;i<now;i++) ans[++cnt]=2;
    	printf("%d
    ",cnt);
    	for (int i=1;i<=cnt;i++) printf("%d
    ",ans[i]); 
    }
    
  • 相关阅读:
    MySQL:批量修改表的排序规则
    Python黑客编程3网络数据监听和过滤
    springboot redis 项目实战 完整篇
    C#读取U盘序列号
    AS3,ReferenceError: Error #1056: 无法为 ×× 创建属性 ×××。
    知道挖掘机如何从货车上下来吗?
    一次进销存软件架构的实践(二)——业务外观层设计
    重构你的软件企业
    遇到了火狐扩展全部丢失的问题
    分布式系统设计原理与方案
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/13387513.html
Copyright © 2020-2023  润新知