zoukankan      html  css  js  c++  java
  • Arc066_E Addition and Subtraction Hard

    传送门

    题目大意

    给定一个加减法的表达式,让你任意的添加合法的括号对,使的表达式最大。

    题解

    考虑到任意左括号一定加在减号右边,那么对于第一个左括号,与该左括号相邻的只含有加号的子序列的贡献一定为负,但是之后的所有数对答案的贡献都可以达到这些数的绝对值,即对于第一个左括号,钦定其对应的右括号在整个表达式的最后,这一段表达式内除去前缀的加法表达式外,对于所有的连续的加法外加一个括号,可以构造形如$$A-(x+x-(x+x+x)-x-x-(x+x))$$使得贡献全部为正但是题目中还有每个括号必须与一个数相邻,不过无伤大雅,因为形如$-(a-(b+c))$等价于$-(a-b)+c$。

    因而引出两种解法。

    解法一:$DP$

    考虑上述构造方法一定满足括号层数不超过$2$,所以可以直接令$F_{i,j=0,1,2}$表示到第$i$个位置有$j$个左括号尚未匹配的答案,转移过程显然。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define M 100020
    #define INF 100000000000000000ll
    using namespace std;
    int read(){
    	int nm=0,fh=1; char cw=getchar();
    	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
    	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
    	return nm*fh;
    }
    LL n,x,F[3];
    int main(){
    	n=read(),F[1]=F[2]=-INF;
    	while(n--){
    		x=read(),F[0]+=x,F[1]-=x,F[2]+=x;
    		if(x<0) F[2]=max(F[1],F[2]),F[1]=max(F[1],F[0]);
    		F[0]=max(F[0],F[1]),F[1]=max(F[1],F[2]);
    	} printf("%lld
    ",F[0]); return 0;
    }
    

    解法二:贪心

    直接用上构造出来的性质,将形如$+a+b+c$的表达式缩成$+x$,保证不会出现两个连续的$+x$,接着枚举第一个左括号的位置,形如$Gspace -space (x+yspace +K$($y$可能不存在)$G$表示前半部分表达式的值,$K$表示后半部分的绝对值的和,用$G+K-|x|-|y|$的值之和更新答案,不要忘了用特判所有符号均为正的情况。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define M 100020
    using namespace std;
    LL read(){
    	LL nm=0,fh=1; LL cw=getchar();
    	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
    	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
    	return nm*fh;
    }
    LL n,p[M],G[M],F[M],ans;
    int main(){
    	n=read();
    	for(LL i=1;i<=n;i++){
    		p[i]=read();
    		if(i>1&&p[i]>0&&p[i-1]>0) p[i-1]+=p[i],i--,n--;
    	}
    	for(LL i=1;i<=n;i++) G[i]=G[i-1]+p[i],F[i]=F[i-1]+abs(p[i]); ans=G[n];
    	for(LL i=2;i<=n;i++) if(p[i-1]<0) ans=max(ans,G[i-1]-p[i]+F[n]-F[i]);
    	printf("%lld
    ",ans); return 0;
    }

     

  • 相关阅读:
    批量拷贝局域网内的文件
    ★★★感谢伤害你的人★★★
    asp 调用子程序不能使用括号 错误解决办法
    喜欢在网上写日志的人是不是都想有朝一日被人看到?
    星语心愿
    执着
    推荐一个.NET(C#)的HTTP辅助类组件restsharp
    如何让DEV跳出的“提示试用版”的对话框不再显示
    Debugging with GDB (3) 退出gdb
    Debugging with GDB (1) 介绍
  • 原文地址:https://www.cnblogs.com/OYJason/p/9810018.html
Copyright © 2011-2022 走看看