• 1350: To Add Which? (优先队列+贪心 或者 数组模拟)


    1350: To Add Which?

          Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 303     Solved: 134    


    Description

        There is an integer sequence with N integers. You can use 1 unit of cost to increase any integer in the sequence by 1.
        Could you tell us the least units of cost to achieve that, the absolute value of difference between any two adjacent integers is not more than D?

    Input

        The first line has one integer T, means there are T test cases.
        For each test case, the first line has two integers N, D (1 <= N <= 105, 0 <= D < 109), which have the same meaning as above. The next line has N integers describing the sequence. Every integer in this sequence is in range [0, 109).
        The size of the input file will not exceed 5MB.

    Output

        For each test case, print an integer in one line, indicates the desired answer.

    Sample Input

    3
    5 2
    1 3 5 3 5
    5 1
    1 2 3 5 6
    5 2
    1 7 3 5 9

    Sample Output

    0
    3
    8

    Hint

    Source

    题目意思:
    给你一个长度为n的序列
    每次操作可以使得序列中某个数加1
    问你最少操作多少次
    可以使得序列相邻的元素的差值的绝对值都是d
    做法:
    做过一个非常非常类似这个题目的题
    是开数组写的
    没有用优先队列
    因为那个时候还不会用优先队列!!!!!
    GG
    大数不会变大,变化的是小数。这个是解题的核心
    贪心的思想
    每次取出序列最大的数,扩展左右2个点。
    比如样例 1 7 3 5 9
    最大是9 扩展左边(无右边) 5+2变成7 刚好相差2  改变后的序列:1 7 3 7 9
    现在9不用看了,弹出队列了
    看最大的7(两个7,就看后面那个吧),现在第二个7左边的3扩展 3+2=5 扩展后的序列 1 7 5 7 9
    现在7弹出了还有 1 7 5
    看最大的7
    扩展7的左边:1+4扩展成5 和7刚好相差2
    再扩展7右边的5,发现不用扩展了
    现在点都扩展了
    在扩展过程中
    记录花费
    就是结果
    注意的地方:
    扩展过的点不用再扩展了
    左端点只有扩展右边
    右端点只要扩展左边
    其余双向扩展
    #include<stdio.h>
    #include<iostream>
    #include<math.h>
    #include<algorithm>
    #include<memory.h>
    #include<memory>
    #include<queue>
    using namespace std;
    #define max_v 1000005
    typedef long long LL;
    int t,n,d;
    LL sum;
    int a[max_v];
    struct node
    {
        int v,id;
        friend bool operator<(node a,node b)
        {
            return a.v<b.v;
        }
    };
    priority_queue<node>q;
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            sum=0;
    
            node p,p1;
    
            while(!q.empty()) q.pop();
    
            scanf("%d%d",&n,&d);
    
            for(int i=0;i<n;i++)
            {
                scanf("%d",&a[i]);
                p.id=i;
                p.v=a[i];
                q.push(p);
            }
    
            while(!q.empty())
            {
                p=q.top();
                q.pop();
    
                if(p.v==a[p.id])
                {
                    if(p.id>=1)
                    {
                        if(p.v-a[p.id-1]>d)
                        {
                            sum+=(p.v-d-a[p.id-1]);
                            a[p.id-1]=p.v-d;
                            p1.v=a[p.id-1];
                            p1.id=p.id-1;
                            q.push(p1);
                        }
                    }
                    if(p.id<n-1)
                    {
                        if(p.v-a[p.id+1]>d)
                        {
                            sum+=(p.v-d-a[p.id+1]);
                            a[p.id+1]=p.v-d;
                            p1.v=a[p.id+1];
                            p1.id=p.id+1;
                            q.push(p1);
                        }
                    }
                }
            }
            printf("%lld
    ",sum);
        }
        return 0;
    }
    /*
    题目意思:
    给你一个长度为n的序列
    每次操作可以使得序列中某个数加1
    问你最少操作多少次
    可以使得序列相邻的元素的差值的绝对值都是d
    
    做法:
    做过一个非常非常类似这个题目的题
    是开数组写的
    没有用优先队列
    因为那个时候还不会用优先队列!!!!!
    GG
    大数不会变大,变化的是小数。这个是解题的核心
    贪心的思想
    每次取出序列最大的数,扩展左右2个点。
    比如样例 1 7 3 5 9
    最大是9 扩展左边(无右边) 5+2变成7 刚好相差2  改变后的序列:1 7 3 7 9
    现在9不用看了,弹出队列了
    看最大的7(两个7,就看后面那个吧),现在第二个7左边的3扩展 3+2=5 扩展后的序列 1 7 5 7 9
    现在7弹出了还有 1 7 5
    看最大的7
    扩展7的左边:1+4扩展成5 和7刚好相差2
    再扩展7右边的5,发现不用扩展了
    现在点都扩展了
    在扩展过程中
    记录花费
    就是结果
    注意的地方:
    扩展过的点不用再扩展了
    左端点只有扩展右边
    右端点只要扩展左边
    其余双向扩展
    
    */

    数组模拟:

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    #define max_v 100005
    typedef long long LL;
    LL a[max_v];
    LL maxx[max_v];
    LL minx[max_v];
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            LL d;
            scanf("%d %lld",&n,&d);
            for(int i=0;i<n;i++)
                scanf("%lld",&a[i]);
    
            maxx[0]=a[0];
            for(int i=1;i<n;i++)
            {
                if(maxx[i-1]-a[i]>d)
                    maxx[i]=maxx[i-1]-d;
                else
                    maxx[i]=a[i];
            }
    
            minx[n-1]=a[n-1];
            for(int i=n-2;i>=0;i--)
            {
                if(minx[i+1]-a[i]>d)
                    minx[i]=minx[i+1]-d;
                else
                    minx[i]=a[i];
            }
    
            LL ans=0;
            for(int i=0;i<n;i++)
                ans+=(max(maxx[i],minx[i])-a[i]);
            printf("%lld
    ",ans);
        }
        return 0;
    }

     

     
  • 相关阅读:
    Delphi 正则表达式之TPerlRegEx 类的属性与方法(3): Start、Stop
    Delphi 正则表达式之TPerlRegEx 类的属性与方法(2): 关于子表达式
    Delphi 正则表达式之TPerlRegEx 类的属性与方法(1): 查找
    Delphi 正则表达式语法(10): 选项
    Delphi 正则表达式语法(9): 临界匹配
    Delphi 正则表达式语法(8): 引用子表达式
    Delphi 正则表达式语法(7): 匹配转义字符
    看阿里P7讲MyBatis:从MyBatis的理解以及配置和实现全帮你搞懂
    公司新来的小姐姐不懂java中的static关键字,这样给她描述不香吗?
    2020阿里,字节跳动,JAVA岗(一线企业校招、社招)面试题合集
  • 原文地址:https://www.cnblogs.com/yinbiao/p/9488557.html
Copyright © 2020-2023  润新知