后缀表达式
Description
给定 N 个加号、M 个减号以及 N + M + 1 个整数 A1, A2, · · · , AN+M+1,小
明想知道在所有由这 N 个加号、M 个减号以及 N + M + 1 个整数凑出的合法的
后缀表达式中,结果最大的是哪一个?
请你输出这个最大的结果。
例如使用1 2 3 + -,则 “2 3 + 1 -” 这个后缀表达式结果是 4,是最大的。
Input
第一行包含两个整数 N 和 M。
第二行包含 N + M + 1 个整数 A1, A2, · · · , AN+M+1。
Output
输出一个整数,代表答案。
Sample Input
1 1
1 2 3
Sample Output
4
后缀表达式相当于加了括号有优先级的式子,!主要考虑负数
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int main()
{
int n,m,a[100001],sum=0,summ=0,nn,num=0,mina=999999;
cin>>m>>n;
nn=n+m+1;
for(int i=0;i<nn;i++)
{
cin>>a[i];
if(a[i]<0)
num++;
sum+=a[i];
summ+=abs(a[i]);
mina=min(mina,abs(a[i]));
}
if(n==num)//负数==负号
cout<<summ<<endl;
else if(n>num)
{
cout<<summ-2*mina<<endl;
}
else if(n<num)
{
if(n==0)//负号为0
cout<<sum<<endl;
else if(num==nn)//全为负数
cout<<summ-2*mina<<endl;
else
{
cout<<summ<<endl;
}
}
return 0;
}
灵能传输
Description
在游戏《星际争霸 II》中,高阶圣堂武士作为星灵的重要 AOE 单位,在游戏的中后期发挥着重要的作用,其技能”灵能风暴“可以消耗大量的灵能对一片区域内的敌军造成毁灭性的伤害。
经常用于对抗人类的生化部队和虫族的刺蛇飞龙等低血量单位。
你控制着 n 名高阶圣堂武士,方便起见标为 1,2,⋅⋅⋅,n。
每名高阶圣堂武士需要一定的灵能来战斗,每个人有一个灵能值 ai 表示其拥有的灵能的多少(ai 非负表示这名高阶圣堂武士比在最佳状态下多余了 ai 点灵能,ai 为负则表示这名高阶圣堂武士还需要 −ai 点灵能才能到达最佳战斗状态)。
现在系统赋予了你的高阶圣堂武士一个能力,传递灵能,每次你可以选择一个 i∈[2,n−1],若 ai≥0 则其两旁的高阶圣堂武士,也就是 i−1、i+1 这两名高阶圣堂武士会从 i 这名高阶圣堂武士这里各抽取 ai 点灵能;若 ai<0 则其两旁的高阶圣堂武士,也就是 i−1,i+1 这两名高阶圣堂武士会给 i 这名高阶圣堂武士 −ai 点灵能。
形式化来讲就是 ai−1+=ai,ai+1+=ai,ai−=2ai。
灵能是非常高效的作战工具,同时也非常危险且不稳定,一位高阶圣堂武士拥有的灵能过多或者过少都不好,定义一组高阶圣堂武士的不稳定度为 maxni=1|ai|,请你通过不限次数的传递灵能操作使得你控制的这一组高阶圣堂武士的不稳定度最小。
Input
本题包含多组询问。输入的第一行包含一个正整数 T 表示询问组数。
接下来依次输入每一组询问。
每组询问的第一行包含一个正整数 n,表示高阶圣堂武士的数量。
接下来一行包含 n 个数 a1,a2,⋅⋅⋅,an。
Output
输出 T 行。
Sample Input
3
3
5 -2 3
4
0 0 0 0
3
1 2 3
Sample Output
3
0
3
More Info
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstring>
using namespace std;
long long nn;
long long n,a[333333];
long long s[333333],s0,sn,maxa=0;
bool book[333333];
int main()
{
cin>>nn;
while(nn--)
{
s[0]=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i];
s[i]+=s[i-1];//输入前缀和
}
s0=0;
sn=s[n];
if(s0>sn)
swap(s0,sn);
sort(s,s+n+1);
for(int i=0;i<=n;i++)//寻找首尾下标
{
if(s[i]==s0)
{
s0=i;
break;
}
}
for(int i=n;i>=0;i--)
{
if(s[i]==sn)
{
sn=i;
break;
}
}
int l=0,r=n;
memset(book,0,sizeof(book));//利用标记数组解决隔一个跳一下的问题
for(int i=s0;i>=0;i-=2)//从尾跳到最小值
{
a[l++]=s[i];
book[i]=true;
}
for(int i=sn;i<=n;i+=2)//从头跳到最大值
{
a[r--]=s[i];
book[i]=true;
}
for(int i=0;i<=n;i++)//从头开始将没遍历过的点遍历一遍
{
if(!book[i])
a[l++]=s[i];
}
maxa=0;
for(int i=1;i<=n;i++)
maxa=max(maxa,abs(a[i]-a[i-1]));//寻找最大值
cout<<maxa<<endl;
}
return 0;
}