题目描述:
期末考试考完了,分数也出来了,大家准备吃糖庆祝一下,为了鼓励同学们下学期能取得更好的成绩,司马红豆同学让n个同学站成一排,如果某个同学的分数比相邻的一个同学要高,那么他得到的糖果就会比这个分数较低的相邻的同学多,每个人至少能得到一个糖果。现在司马红豆想要知道最少需要多少个糖果能完成分糖任务。
输入格式:
第一行输入一个整数n, (1≤n≤100000)
第二行输入n 个整数,依次表示排成一排后每位同学的分数ai, (1≤ai≤1000)。
输出格式:
输出一个整数,表示最少需要的糖果数量
样例输入1:
3 1 0 2
样例输出1:
5
样例输入2:
3 1 2 2
样例输出2:
4
思路:
from:https://www.cnblogs.com/stxy-ferryman/p/9314491.html
我们把较小糖果数的一个人向相邻的较大糖果数的一个人连一条边,建立图。
然后跑一遍dfs,O(N)遍历完整个图,求出每个点到入度为0点的最大距离+1,求和即是答案。
代码:
#include<iostream>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#include<string.h>
#include<queue>
#include<stack>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=100000+6;
#define mod 1000000007
#define INF 0x3f3f3f3f
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
int a[maxn];
vector<int>v[maxn];
int f[maxn];
int du[maxn];
void dfs(int now,int step)
{
f[now]=max(f[now],step);
for(int i=0;i<v[now].size();i++)
{
dfs(v[now][i],step+1);
}
return ;
}
int main()
{
int n;
cin>>n;
rep(i,1,n)
{
cin>>a[i];
if(a[i]>a[i-1])
{
v[i-1].push_back(i);
du[i]++;
}
else if(a[i]<a[i-1])
{
v[i].push_back(i-1);
du[i-1]++;
}
}
rep(i,1,n)
{
if(!du[i])
{
dfs(i,1);
}
}
ll ans=0;
rep(i,1,n)
{
ans+=f[i];
}
cout<<ans<<endl;
}