Codeforces Round #523 (Div. 2) B,D

本文探讨了两个算法问题:一是如何在不影响摄像头视角的情况下从展览中移除最多数量的积木;二是如何以最低成本观看所有电视节目,考虑到租用电视的费用和额外分钟数的成本。

B

You came to the exhibition and one exhibit has drawn your attention. It consists of n stacks of blocks, where the i-th stack consists of ai

blocks resting on the surface.

The height of the exhibit is equal to m

. Consequently, the number of blocks in each stack is less than or equal to m

.

There is a camera on the ceiling that sees the top view of the blocks and a camera on the right wall that sees the side view of the blocks.

Find the maximum number of blocks you can remove such that the views for both the cameras would not change.

Note, that while originally all blocks are stacked on the floor, it is not required for them to stay connected to the floor after some blocks are removed. There is no gravity in the whole exhibition, so no block would fall down, even if the block underneath is removed. It is not allowed to move blocks by hand either.

Input

The first line contains two integers n

and m (1≤n≤100000, 1≤m≤109

) — the number of stacks and the height of the exhibit.

The second line contains n

integers a1,a2,…,an (1≤ai≤m

) — the number of blocks in each stack from left to right.

Output

Print exactly one integer — the maximum number of blocks that can be removed.

思路 : 我们把每一列从小到大排序;然后贪心,每一排最少可以移除到只剩一个,遇到某一排在当前情况下需要保留多个的情况,也就是说如果后面存在相邻两排高度相等时,是可以移除的,我们把后面有可能移除的个数res记录下来,遇到两排相登时,--直到res为0;

 

#include<bits/stdc++.h>

using namespace std;

int a[100005];

int main()
{
    int n, m;
    cin >> n >> m;
    long long mx =0;
    for(int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    sort(a, a+n);
//    for(int i = 0; i < n; i++)
    //    cout << a[i] << " ";
    cout << endl;
    int s = 0, num = a[0]-1;
    for(int  i = 1; i < n; i++)
    {
        if(a[i] == a[i-1])
        {
            if(num)
            {
                mx += a[i];
                num--;
            }
            else
                mx += (a[i]-1);
        }
        else
        {
            mx += a[i-1];
            num += (a[i]-a[i-1]-1);
        }
    //    cout << mx << endl;
    }
    cout << mx << endl;
}
/*

5 8
2 4 4 5 5

*/

 

D

There are n TV shows you want to watch. Suppose the whole time is split into equal parts called "minutes". The i-th of the shows is going from li-th to ri

-th minute, both ends inclusive.

You need a TV to watch a TV show and you can't watch two TV shows which air at the same time on the same TV, so it is possible you will need multiple TVs in some minutes. For example, if segments [li,ri]

and [lj,rj] intersect, then shows i and j

can't be watched simultaneously on one TV.

Once you start watching a show on some TV it is not possible to "move" it to another TV (since it would be too distracting), or to watch another show on the same TV until this show ends.

There is a TV Rental shop near you. It rents a TV for x

rupees, and charges y (y<x) rupees for every extra minute you keep the TV. So in order to rent a TV for minutes [a;b] you will need to pay x+y⋅(b−a)

.

You can assume, that taking and returning of the TV doesn't take any time and doesn't distract from watching other TV shows. Find the minimum possible cost to view all shows. Since this value could be too large, print it modulo 109+7

.

Input

The first line contains integers n

, x and y (1≤n≤105, 1≤y<x≤109

) — the number of TV shows, the cost to rent a TV for the first minute and the cost to rent a TV for every subsequent minute.

Each of the next n

lines contains two integers li and ri (1≤li≤ri≤109) denoting the start and the end minute of the i

-th TV show.

Output

Print exactly one integer — the minimum cost to view all the shows taken modulo 109+7

.

Examples

Input

Copy

5 4 3
1 2
4 10
2 4
10 11
5 9

Output

Copy

60

Input

Copy

6 3 2
8 20
6 22
4 15
20 28
17 25
20 27

Output

Copy

142

Input

Copy

2 1000000000 2
1 2
2 3

Output

Copy

999999997

思路:

看数据就知道只能O(nlogn),O(n)做;考虑O(n)的做法。花费 = x*电视数目+y*节目时长+y*中间空闲时长;

节目时长很简单,只需要考虑数目和空闲时间,对于每一段空闲时长*y一定是小于x的;具体看代码。

#include<bits/stdc++.h>

using namespace std;
#define ll long long
const int mod = 1e9 + 7;
int s[100005], e[100005];
priority_queue<int> hay;
int main()
{
    int n , x, y;
    while(cin >> n >> x >> y)
    {
        int ss =0, ee=0;
        ll ans = 0;
        for(int i = 0; i < n; i++)
        {
            cin >> s[i] >> e[i];
            ans += (ll)(e[i]-s[i])*y%mod;
            ans %= mod;
        }
    //    cout << ans << endl;
        sort(s, s+n);
        sort(e, e+n);
        while(ss < n && ee < n)
        {
            if(s[ss] > e[ee])
            {
                hay.push(e[ee++]);
            }
            else
            {
                int tmp = s[ss];
                if(!hay.empty() && (ll)(tmp-hay.top())*y >= x)
                {
                    while (!hay.empty()) hay.pop();
                }
                if(hay.empty())
                {
                    ans += x;
                    ans %= mod;
                }
                else
                {
                    ans += (ll)(tmp-hay.top())*y;
                    ans %= mod;
                    hay.pop();
                }
            //    cout << ans << endl;
                ss++;
            }
        }
        cout << ans << endl;
    }
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值