【codeforces VK Cup Round 1】BDE题解

B. Group Photo 2 (online mirror version)

time limit per test2 seconds

memory limit per test256 megabytes

inputstandard input

outputstandard output

Many years have passed, and n friends met at a party again. Technologies have leaped forward since the last meeting, cameras with timer appeared and now it is not obligatory for one of the friends to stand with a camera, and, thus, being absent on the photo.

Simply speaking, the process of photographing can be described as follows. Each friend occupies a rectangle of pixels on the photo: the i-th of them in a standing state occupies a wi pixels wide and a hi pixels high rectangle. But also, each person can lie down for the photo, and then he will occupy a hi pixels wide and a wi pixels high rectangle.

The total photo will have size W?×?H, where W is the total width of all the people rectangles, and H is the maximum of the heights. The friends want to determine what minimum area the group photo can they obtain if no more than n?/?2 of them can lie on the ground (it would be strange if more than n?/?2 gentlemen lie on the ground together, isn’t it?..)

Help them to achieve this goal.

Input

The first line contains integer n (1?≤?n?≤?1000) — the number of friends.

The next n lines have two integers wi,?hi (1?≤?wi,?hi?≤?1000) each, representing the size of the rectangle, corresponding to the i-th friend.

Output

Print a single integer equal to the minimum possible area of the photo containing all friends if no more than n?/?2 of them can lie on the ground.

Sample test(s)

input

3

10 1

20 2

30 3

output

180

input

3

3 1

2 2

4 3

output

21

input

1

5 10

output

50

思路题。

1.枚举最高的人是第i个,高度为m

2.扫描剩下的n个人,如果有h>m的,计数器cnt++,表明这个人必须躺下

3.如果cnt>n/2,说明m这个高度一定不能当最高的,返回第一步继续枚举

4.在上述过程中,我们同时求出w的和为now。

如果再让一些人躺下,可以使now变小,使答案更优。

除了必须要躺下的cnt,我们还可以再另n/2?cnt个人躺下,来优化答案,这些人必须满足的条件为①a[j].h≤m②a[j].w≤m,否则j这个人就变成最高的了。

我们把a[j].h?a[j].w加入递增的优先队列,取出前n/2?cnt个<0的加到now中就是对答案的优化了。

注意:一开始这个题WA了,因为最高的高度m可能是某个人的w,即让他躺下的高度。。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
int n;
struct data
{
    int w,h;
}a[1005];
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        scanf("%d%d",&a[i].w,&a[i].h);
    int ans=1e9+5;
    for (int i=1;i<=n;i++)
    {
        int m=a[i].h,now=a[i].w,cnt=0;
        for (int j=1;j<=n;j++)
        {
            if (j!=i&&a[j].h>m)
                cnt++;
            if (a[j].h>m&&a[j].w>m)
                cnt=n+5;
        }
        if (cnt<=n/2)
        {
        for (int j=1;j<=n;j++)
            if (j!=i)
            {
                if (a[j].h>m) now+=a[j].h;
                else
                {
                    now+=a[j].w;
                    if (a[j].w<=m)
                        q.push(a[j].h-a[j].w);
                }
            }
        while (cnt<n/2&&!q.empty())
        {
            int x=q.top();
            if (x>=0) break;
            now+=x;
            q.pop();
            cnt++;
        }
        while (!q.empty())
            q.pop();
        ans=min(ans,m*now);
        }
        m=a[i].w,now=a[i].h,cnt=1;
        for (int j=1;j<=n;j++)
        {
            if (j!=i&&a[j].h>m)
                cnt++;
            if (a[j].h>m&&a[j].w>m)
                cnt=n+5;
        }
        if (cnt>n/2) continue;
        for (int j=1;j<=n;j++)
            if (j!=i)
            {
                if (a[j].h>m) now+=a[j].h;
                else
                {
                    now+=a[j].w;
                    if (a[j].w<=m)
                        q.push(a[j].h-a[j].w);
                }
            }
        while (cnt<n/2&&!q.empty())
        {
            int x=q.top();
            if (x>=0) break;
            now+=x;
            q.pop();
            cnt++;
        }
        while (!q.empty())
            q.pop();
        ans=min(ans,m*now);
    }
    printf("%d\n",ans);
    return 0;
}

D. Social Network

time limit per test2 seconds

memory limit per test256 megabytes

inputstandard input

outputstandard output

Polycarpus got an internship in one well-known social network. His test task is to count the number of unique users who have visited a social network during the day. Polycarpus was provided with information on all user requests for this time period. For each query, we know its time… and nothing else, because Polycarpus has already accidentally removed the user IDs corresponding to the requests from the database. Thus, it is now impossible to determine whether any two requests are made by the same person or by different people.

But wait, something is still known, because that day a record was achieved — M simultaneous users online! In addition, Polycarpus believes that if a user made a request at second s, then he was online for T seconds after that, that is, at seconds s, s?+?1, s?+?2, …, s?+?T?-?1. So, the user’s time online can be calculated as the union of time intervals of the form [s,?s?+?T?-?1] over all times s of requests from him.

Guided by these thoughts, Polycarpus wants to assign a user ID to each request so that:

the number of different users online did not exceed M at any moment,

at some second the number of distinct users online reached value M,

the total number of users (the number of distinct identifiers) was as much as possible.

Help Polycarpus cope with the test.

Input

The first line contains three integers n, M and T (1?≤?n,?M?≤?20?000, 1?≤?T?≤?86400) — the number of queries, the record number of online users and the time when the user was online after a query was sent. Next n lines contain the times of the queries in the format “hh:mm:ss”, where hh are hours, mm are minutes, ss are seconds. The times of the queries follow in the non-decreasing order, some of them can coincide. It is guaranteed that all the times and even all the segments of type [s,?s?+?T?-?1] are within one 24-hour range (from 00:00:00 to 23:59:59).

Output

In the first line print number R — the largest possible number of distinct users. The following n lines should contain the user IDs for requests in the same order in which the requests are given in the input. User IDs must be integers from 1 to R. The requests of the same user must correspond to the same identifiers, the requests of distinct users must correspond to distinct identifiers. If there are multiple solutions, print any of them. If there is no solution, print “No solution” (without the quotes).

Sample test(s)

input

4 2 10

17:05:53

17:05:58

17:06:01

22:39:47

output

3

1

2

2

3

input

1 2 86400

00:00:00

output

No solution

Note

Consider the first sample. The user who sent the first request was online from 17:05:53 to 17:06:02, the user who sent the second request was online from 17:05:58 to 17:06:07, the user who sent the third request, was online from 17:06:01 to 17:06:10. Thus, these IDs cannot belong to three distinct users, because in that case all these users would be online, for example, at 17:06:01. That is impossible, because M?=?2. That means that some two of these queries belonged to the same user. One of the correct variants is given in the answer to the sample. For it user 1 was online from 17:05:53 to 17:06:02, user 2 — from 17:05:58 to 17:06:10 (he sent the second and third queries), user 3 — from 22:39:47 to 22:39:56.

In the second sample there is only one query. So, only one user visited the network within the 24-hour period and there couldn’t be two users online on the network simultaneously. (The time the user spent online is the union of time intervals for requests, so users who didn’t send requests could not be online in the network.)

贪心。

当计算到第i个时间的时候,已经有now个不同的人:

①如果之前能到达这个时间的人数<M,我们直接把这个人设为第now+1个人即可

②如果之前能到达这个时间的人已经有M个了,那么这个人一定不能设为第now+1个,这个人应该设为这M人中的哪一个最优呢?

最靠后的那一个!

因为不能到达第i+1个时间的人必然是最靠前的几个,如果把当前这个人设成靠前的人k,那么k很有可能就能到达第i+1个时间了,对以后不利;所以设成最靠后的人对以后最有利。

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#define N 20005
using namespace std;
int a[N],n,M,T,q[N],ans[N];
int main()
{
    cin>>n>>M>>T;
    for (int i=1;i<=n;i++)
    {
        int h,m,s;
        scanf("%d:%d:%d",&h,&m,&s);
        a[i]=h*3600+m*60+s;
    }
    int h=1,t=0,ok=0,now=0;
    for (int i=1;i<=n;i++)
    {
        while (h<t&&q[h]<a[i])
            h++;
        if (t-h+1<M)
        {
            q[++t]=a[i]+T-1;
            ans[i]=++now;
        }
        else
        {
            q[t]=a[i]+T-1;
            ans[i]=now;
        }
        if (t-h+1==M) ok=1;
    }
    if (ok)
    {
        printf("%d\n",now);
        for (int i=1;i<=n;i++)
            printf("%d\n",ans[i]);
    }
    else
        puts("No solution");
    return 0;
}

E. The Art of Dealing with ATM

time limit per test2 seconds

memory limit per test256 megabytes

inputstandard input

outputstandard output

ATMs of a well-known bank of a small country are arranged so that they can not give any amount of money requested by the user. Due to the limited size of the bill dispenser (the device that is directly giving money from an ATM) and some peculiarities of the ATM structure, you can get at most k bills from it, and the bills may be of at most two distinct denominations.

For example, if a country uses bills with denominations 10, 50, 100, 500, 1000 and 5000 burles, then at k?=?20 such ATM can give sums 100?000 burles and 96?000 burles, but it cannot give sums 99?000 and 101?000 burles.

Let’s suppose that the country uses bills of n distinct denominations, and the ATM that you are using has an unlimited number of bills of each type. You know that during the day you will need to withdraw a certain amount of cash q times. You know that when the ATM has multiple ways to give money, it chooses the one which requires the minimum number of bills, or displays an error message if it cannot be done. Determine the result of each of the q of requests for cash withdrawal.

Input

The first line contains two integers n, k (1?≤?n?≤?5000, 1?≤?k?≤?20).

The next line contains n space-separated integers ai (1?≤?ai?≤?107) — the denominations of the bills that are used in the country. Numbers ai follow in the strictly increasing order.

The next line contains integer q (1?≤?q?≤?20) — the number of requests for cash withdrawal that you will make.

The next q lines contain numbers xi (1?≤?xi?≤?2·108) — the sums of money in burles that you are going to withdraw from the ATM.

Output

For each request for cash withdrawal print on a single line the minimum number of bills it can be done, or print ?-?1, if it is impossible to get the corresponding sum.

Sample test(s)

input

6 20

10 50 100 500 1000 5000

8

4200

100000

95000

96000

99000

10100

2015

9950

output

6

20

19

20

-1

3

-1

-1

input

5 2

1 2 3 5 8

8

1

3

5

7

9

11

13

15

output

1

1

1

2

2

2

2

-1

(因为最多只有两种面额,一开始想直接暴力枚举,但还是TLE了)

用一个map:mp[i]表示得到i的钞票最少需要取mp[i]次钱,只要枚举每种钞票取1到k次,不断更新即可。

(注意mp[0]=0)

预处理好之后,对于每一个询问x,我们遍历整个mp[],看能否找到x?mp[i],根据各自所需的钞票数更新答案即可。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <map>
#define LL long long
using namespace std;
map<LL,int> mp;
map<LL,int>:: iterator it;
int a[5005],n,k,q;
int main()
{
    scanf("%d%d",&n,&k);
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=k;j++)
            if (mp.count(j*a[i])) mp[j*a[i]]=min(mp[j*a[i]],j);
            else mp[j*a[i]]=j;
    mp[0]=0;
    scanf("%d",&q);
    while (q--)
    {
        int x,ans=k+1;
        scanf("%d",&x);
        for (it=mp.begin();it!=mp.end();it++)
            if (mp.count(x-it->first))
                ans=min(ans,mp[x-it->first]+it->second);
        if (ans>k) printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}

(这场比赛BDE应该是最简单的三道,全是乱搞题。。)

时间: 2024-10-07 06:13:33

【codeforces VK Cup Round 1】BDE题解的相关文章

Codeforces VK Cup 2015 Wild Card Round 1 (AB)

比赛链接:http://codeforces.com/contest/522 A. Reposts time limit per test:1 second memory limit per test:256 megabytes One day Polycarp published a funny picture in a social network making a poll about the color of his handle. Many of his friends started

codeforces VK cup 2016-round 1 D.Bear and Contribution

题意大概就是有n个数字,要使至少有k个相同,可以花费b使一个数+5,可以花费c使一个数+1,求最小花费. 要对齐的数肯定是在[v,v+4]之间,所以分别枚举模为0~4的情况就可以了. 排序一下,然后化绝对为相对 例如有 3 6 8 14这4个数,模4, 耗费分别为c+2b 3c+b c+b 0 可以-2b(移动到14时=2*5+4,倍率2)变成c 3c-b c-b -2b 就是说每次都取倍率然后减其花费压入优先队列,若元素数量大于k就弹出最大的那个就可以了 /*没时间自己写个就把其他人的题解搞来

Codeforces VK Cup 2015 A.And Yet Another Bracket Sequence(后缀数组+平衡树+字符串)

这题做得比较复杂..应该有更好的做法 题目大意: 有一个括号序列,可以对其进行两种操作: ·        向里面加一个括号,可以在开头,在结尾,在两个括号之间加. ·        对当前括号序列进行循环移动,即把最后一个括号拿到开头来. 上述两种操作可以做任意次,要求添加最少的括号使得原序列变成一个合法括号序列.如果有多种可能,输出字典序最小的那一个."(" < ")". 题解: 首先计算左括号和右括号的数量,可以知道,不妨假设左括号的数量大于右括号 那么

Codeforces VK Cup Finals #424 Div.1 C. Bamboo Partition(数论)

题目要求符合以下条件的最大的d 化简得 注意到 最多只有2*sqrt(a[i]-1)种取值,也就是一共最多有n*sqrt(10^19)种取值,于是枚举一下d,计算出符合上上式的最大的d更新答案,然后d跳跃到下一个取值 效率O(n²sqrt(10^9)) #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=110,inf=1e9; ll n,k,ans,r; ll a[maxn]; vo

Codeforces VK Cup Finals #424 Div.1 A. Office Keys(DP)

显然是不可能交叉取钥匙的,于是把钥匙和人都按坐标排序就可以DP了 钥匙可以不被取,于是f[i][j]表示前i个钥匙被j个人拿的时间 f[i][j]=min(f[i-1][j],max(f[i-1][j-1],abs(b[i]-a[j])+abs(P-b[i])); #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=1010,inf=2e9; int n,k,p; int a[maxn

Codeforces VK Cup 2018 Div.2

总题面传送门 这次考试只过了3题,前三题题目难度并不大,但是第三题的代码细节卡了我两个半小时(基本上整场考试),所以以后要合理把握时间,注意把握代码细节,并更加完善我的代码风格,使其更加简练.(赛外话). A:较简单的模拟题,但是注意对于刚开始的航班不需要S*2. B:贪心题.显然我们一定会先将Si值最大的堵住,然后是次大的...所以只要Sort一遍从大到小将不是水管1的堵住判断一下是否符合条件就行 . C:二分.显然对于一对点,最优的显然是他们y之间的点,(有电梯当然选电梯).否则就到它们两侧

Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) A. Single Wildcard Pattern Matching B. Pair of Toys C. Bracket Subsequence D. Array Restoration-区间查询最值(RMQ(ST))

Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) A. Single Wildcard Pattern Matching 题意就是匹配字符的题目,打比赛的时候没有看到只有一个" * ",然后就写挫了,被hack了,被hack的点就是判一下只有一个" * ". 1 //A 2 #include<iostream> 3 #include<cstdio&g

【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps

我们要统计的答案是sigma([L/K]),L为路径的长度,中括号表示上取整. [L/K]化简一下就是(L+f(L,K))/K,f(L,K)表示长度为L的路径要想达到K的整数倍,还要加上多少. 于是,我们现在只需要统计sigma((L+f(L,K))),最后除以K即可. 统计sigma(L)时,我们考虑计算每条边出现在了几条路径中,设u为edgei的子节点,那么这条边对答案的贡献就是siz(u)*(n-siz(u)),siz(u)为u的子树大小. 统计sigma(f(L,K))时,我们需要dp出

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) E. DNA Evolution 树状数组

E. DNA Evolution time limit per test 2 seconds memory limit per test 512 megabytes input standard input output standard output Everyone knows that DNA strands consist of nucleotides. There are four types of nucleotides: "A", "T", "