• 第十三届蓝桥杯C++C组省赛H题—— 重新排序(AC)


    1.重新排序

    1.题目描述

    给定一个数组 A A A 和一些查询 L i , R i L_{i}, R_{i} Li,Ri 求数组中第 L i L_{i} Li至第 R i R_{i} Ri个元素之和。小蓝觉得这个问题很无聊, 于是他想重新排列一下数组, 使得最终每个查询结果的和尽可能地大。小蓝想知道相比原数组, 所有查询结果的总和最多可以增加多少?

    2.输入格式

    输入第一行包含一个整数 n n n

    第二行包含 n n n 个整数 A 1 , A 2 , ⋯   , A n A_{1}, A_{2}, \cdots, A_{n} A1,A2,,An , 相邻两个整数之间用一个空格分隔。
    第三行包含一个整数 m m m 表示查询的数目。

    接下来 m m m 行, 每行包含两个整数 L i 、 R i L_{i} 、 R_{i} LiRi, 相邻两个整数之间用一个空格分隔。

    3.输出格式

    输出一行包含一个整数表示答案。

    4.样例输入

    5
    1 2 3 4 5
    2
    1 3
    2 5

    5.样例输出

    4

    6.样例说明

    原来的和为 6 + 14 = 20 6+14=20 6+14=20, 重新排列为 ( 1 , 4 , 5 , 2 , 3 ) (1,4,5,2,3) (1,4,5,2,3) 后和为 10 + 14 = 24 10+14=24 10+14=24, 增加了4。

    7.数据范围

    1 ≤ n , m ≤ 1 0 5 , 1 ≤ A i ≤ 1 0 6 , 1 ≤ L i ≤ R i ≤ 1 0 6 1≤n,m≤10^5,1≤Ai ≤10^6 ,1≤Li ≤Ri ≤10^6 1n,m105,1Ai106,1LiRi106

    8.原题链接

    重新排序

    2.解题思路

    一道Codeforces上的原题,只不过原题没有问和增加多少,贪心的思路也比较好想,不知道为什么会是 H H H 题。查询最多能增加多少的和,其实就是用重排以后的查询和减去未重排的查询总和,未重排的查询总和是不变的,所以我们只需要最大化使得重排之后的查询总和最大。

    只有处在查询区间数,值才会加到我们的计算当中,明显查询的区间有可能会重合,也就是说会存在某个位置的数多次处在查询区间中作为答案被统计,为了使得总和最大化,我们自然贪心地将值更大的数放在这些位置。

    先统计出每个位置被统计的频率,也就是当查询区间为 [ l , r ] [l,r] [l,r]时,这个区间的值全部加1,代表被统计一次,这个操作我们可以使用差分实现。在统计出未排序原数组的和res,我们将原数组排序,然后不断加上当前最大数乘上当前最大出现次数,贪心得到最大排序后的和ans,答案即为ans-res

    3.Ac_code

    Java

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    
    public class Main {
        static int N=100010;
        static int[] a=new int[N];
        static long[] s=new long[N];
        //差分数组
        static long[] g=new long[N];
        static int n;
        static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        public static void main(String[] args) throws IOException {
            n=Integer.parseInt(br.readLine());
            String[] v=br.readLine().split(" ");
            for (int i = 1; i <=n; i++) {
                a[i]=Integer.parseInt(v[i-1]);
                s[i]=s[i-1]+a[i];
            }
            int m=Integer.parseInt(br.readLine());
            long res=0;
            for (int i = 0; i < m; i++) {
                v=br.readLine().split(" ");
                int l=Integer.parseInt(v[0]);
                int r=Integer.parseInt(v[1]);
                g[l]++;
                g[r+1]--;
                res+=s[r]-s[l-1];
            }
            for (int i = 1; i <=n; i++) {
                g[i]+=g[i-1];
            }
            long ans=0;
            Arrays.sort(a);
            Arrays.sort(g);
            int pre=g.length-1;
            while (g[pre]!=0){
                ans+=g[pre] *a[pre];
                pre--;
            }
            System.out.println(ans-res);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    C++

    #include
    using namespace std;
    typedef long long LL;
    const int N = 200010;
    
    int n, m;
    LL a[N], s[N], g[N];
    void solve()
    {
    	cin >> n;
    	for (int i = 1; i <= n; ++i) {
    		cin >> a[i];
    		s[i] += s[i - 1] + a[i];
    	}
    	cin >> m;
    	LL res = 0;
    	for (int i = 0; i < m; ++i)
    	{
    		int l, r;
    		cin >> l >> r;
    		g[l]++, g[r + 1]--;
    		res += s[r] - s[l - 1];
    	}
    	for (int i = 1; i <= n; i++) {
    		g[i] += g[i - 1];
    	}
    	LL ans = 0;
    	sort(a + 1, a + n + 1);
    	sort(g + 1, g + n + 1);
    	int pre = n;
    	while (g[pre] != 0) {
    		ans += g[pre] * a[pre];
    		pre--;
    	}
    	cout<<ans-res<<'\n';
    }
    int main()
    {
    	ios_base :: sync_with_stdio(false);
    	cin.tie(nullptr);
    	int t = 1;
    	while (t--)
    	{
    		solve();
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
  • 相关阅读:
    使用SRM系统有哪些供应商管理优势?
    微信小程序基础
    MySQL数据库的主从复制与读写分离
    【分享】5G+北斗RTK高精度人员定位解决方案
    多线程-异步编排
    现有TiDB集群扩展pump/drainer作为binlog文件落地
    飞桨图像分割套件PaddleSeg初探
    【自撰写】【国际象棋入门】第7课 常见战术分析(二)牵制、驱赶和腾挪
    交换机和工业级4G路由器的区别
    群狼调研(长沙后勤服务满意度调查)开展物业满意度入户调查
  • 原文地址:https://blog.csdn.net/m0_57487901/article/details/127773496