E: Carryon分糖果

版权声明:个人笔记,仅供复习 https://blog.csdn.net/weixin_42373330/article/details/88973807

E: Carryon分糖果
题目描述
Carryon最近在带学弟刷题,让学弟们打了一场比赛,一共有n个学弟,第i个人的分数为a[i],现在想要给他们分一些糖果作为奖励。将他们围成一个圈发糖,但是怕他们心里不平衡就制定了一些规则。

1.每个人只能看到旁边人的分数和糖果数

2.分数高的得到的糖果比分数低的多

3.每个人至少一个糖果

现在想用最少的糖果来解决这个问题,请输出最终所需要的糖果数。

输入
第一行输入T表示有多少组;(T <= 100)

每组输入为一个整数n,表示学弟的个数。(0 < n <= 10000)

接下来输入n个an[i],表示他们所得的分数。(0 < an[i] < 100000)

输出
输出所需最少的糖果数

样例输入
2
20
2 2 6 7 7 6 5 4 3 1 3 5 7 9 10 10 12 10 10 10
13
2 3 4 4 5 6 7 6 7 6 5 3 2
样例输出
55
32
提示
样例解释:

对于第一个样例当糖果按下面分则最少

1 1 2 3 6 5 4 3 2 1 2 3 4 5 6 1 2 1 1 2

所以答案为55

对于第二样例当糖果按下面分则最少

1 2 3 1 2 3 4 1 5 4 3 2 1

所以答案为32


分析:
①每次从最小的开始,如果两边比它大,往两边延伸(类似v字);直到所有的位置都遍历完;
②判断两个v的接触部分,是否符合题目规则,处理下不符合的

代码:

#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
#define ll long long
const int N = 1e5+10;
struct p
{
    int id;//在a数组中的位置
    int value;//在a数组中的值
};
bool cmp(p a,p b)
{
    return a.value<b.value;
}
int a[N];
int val[N];
int vis[N];
int t;
int n;
ll sum = 0;
vector<p> v;
int duv[N];//记录左断点位置
ll f()
{

    int len=0;
    for(int i=0;i<v.size();i++)
    {
       p x=v[i];
       int id =  x.id;
       if(vis[id]) continue;
       sum+=1;
       vis[id] = 1;
       int k=id;//向右
       int j=id;//向左
       //往两边延伸,像个v字行
       int cnt1=1;
       int cnt2=1;
       val[id]=1;
       
       while(a[(k+1)%n]>a[k%n]&&!vis[(k+1)%n])
       {
           cnt1++;

           vis[(k+1)%n]=1;

           sum+=cnt1;
           val[(k+1)%n]=cnt1;
           k=(k+1)%n;
       }
       while(a[(j-1+n)%n]>a[j%n]&&!vis[(j-1+n)%n])
       {
           cnt2++;

           vis[(j-1+n)%n]=1;

           sum+=cnt2;
           val[(j-1+n)%n]=cnt2;
           j=(j-1+n)%n;
       }
       if(!(a[(k+1)%n]>a[k%n]&&!vis[(k+1)%n])) duv[len++]= k%n;//记录左断点位置

    }

    for(int i=0;i<len;i++)//判断
    {
        int le=duv[i];
        int ri=(le+1)%n;
        if(a[le]>a[ri])
        {
            if(val[le]<=val[ri]) sum+=val[ri]-val[le]+1;
        }
        else if(a[le]==a[ri])
        {
            continue;
        }
        else //小于
        {
            if(val[le]>=val[ri]) sum+=val[le]-val[ri]+1;
        }
    }
    return sum;

}



int main()
{
    scanf("%d",&t);
    while(t--)
    {
        sum = 0;
        scanf("%d",&n);
        v.clear();
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            p x;
            x.id=i;
            x.value=a[i];
            v.push_back(x);
        }

        sort(v.begin(),v.end(),cmp);

        cout<<f()<<endl;

    }




    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42373330/article/details/88973807
E
e'e
今日推荐