https://atcoder.jp/contests/nomura2020/tasks/nomura2020_c
atc全是贪心和数数题就不适合我这种弱智选手。。。
DEF qls和cf黑名都想不出来的数数。。。还是不补了,这个C也想了好久。。。
这题就先算出每一层的最多的节点个数(代码中同时求了最少的节点个数然而没啥用)
从上往下算的时候,如果某个a[i]超过了这层最多可能有的节点,就直接ans=-1
然后从最后一层向上讨论,最后一层一定是a[n]的点,然后最多向上就是一人一个父节点,如果这个数量大于mx[n-1],就把当前节点的数量变成mx[n-1],一层一层向上本层最多多少点就行了。由于预处理的时候判断过,所以向上求的一定是合法的
注意特判n=0的情况
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
const ll inf=1e13;
int n,m,cas,k;
int a[maxl],b[maxl];
char s[maxl];
bool in[maxl];
ll ans;
ll mi[maxl],mx[maxl];
inline void prework()
{
scanf("%d",&n);
for(int i=0;i<=n;i++)
scanf("%d",&a[i]);
}
inline void mainwork()
{
if(n==0)
{
if(a[0]==1)
ans=1;
else
ans=-1;
return;
}
mi[0]=1;mx[0]=1;
for(int i=1;i<=n;i++)
{
mi[i]=mi[i-1]-a[i-1];
mx[i]=(mx[i-1]-a[i-1])*2;
if(mi[i]<a[i]) mi[i]=a[i];
if(mx[i]>inf) mx[i]=inf;
if(mi[i]>mx[i])
{
ans=-1;
return;
}
}
ll now=a[n];
for(int i=n;i>=1;i--)
{
ans+=now;
if(now+a[i-1]>mx[i-1])
now=mx[i-1];
else
now=now+a[i-1];
}
ans+=1;
}
inline void print()
{
printf("%lld",ans);
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}