Test on 11/17/2018
第一次参加cf比赛,水了一发写了三道水题实在不想写了,然后Rating就低了,好难过哈哈哈哈。
D:Cutting Out
Description
You are given an array ss consisting of nn integers.
You have to find any array tt of length kk such that you can cut out maximum number of copies of array tt from array ss.
Cutting out the copy of tt means that for each element titi of array tt you have to find titi in ss and remove it from ss. If for some titi you cannot find such element in ss, then you cannot cut out one more copy of tt. The both arrays can contain duplicate elements.
For example, if s=[1,2,3,2,4,3,1]s=[1,2,3,2,4,3,1] and k=3k=3 then one of the possible answers is t=[1,2,3]t=[1,2,3]. This array tt can be cut out 22 times.
- To cut out the first copy of tt you can use the elements [1,2––,3,2,4,3––,1––][1,2_,3,2,4,3_,1_] (use the highlighted elements). After cutting out the first copy of tt the array ss can look like [1,3,2,4][1,3,2,4].
- To cut out the second copy of tt you can use the elements [1––,3––,2––,4][1_,3_,2_,4]. After cutting out the second copy of tt the array ss will be [4][4].
Your task is to find such array tt that you can cut out the copy of tt from ss maximum number of times. If there are multiple answers, you may choose any of them.
Input
The first line of the input contains two integers nn and kk (1≤k≤n≤2⋅1051≤k≤n≤2⋅105) — the number of elements in ss and the desired number of elements in tt, respectively.
The second line of the input contains exactly nn integers s1,s2,…,sns1,s2,…,sn (1≤si≤2⋅1051≤si≤2⋅105).
Output
Examples
Input
7 3
1 2 3 2 4 3 1
Output
1 2 3
Input
10 4
1 3 1 3 10 3 7 7 12 3
Output
7 3 1 3
Input
15 2
1 2 1 1 1 2 1 1 2 1 2 1 1 1 1
Output
1 1
Hint
The first example is described in the problem statement.
In the second example the only answer is [7,3,1,3][7,3,1,3] and any its permutations. It can be shown that you cannot choose any other array such that the maximum number of copies you can cut out would be equal to 22.
In the third example the array tt can be cut out 55 times.
正确解法:
题目的意思是在n个数中找出k个数,使这k个数在n个数中出现的最多。
给定n和k,求这k个数。
这题目一开始就把我弄懵了,原本想到了桶排序,然后按出现的次数大小排序,找出前k个就好。但是这样的话就不会有重复的,也就是说不是题目所要的。于是我就不会写了。
看答案很简单啊,不过还要多想想。
还是桶排序,然后从1-n开始二分,找出有k个数,在n个数中出现的最大的次数。
因为数最多出现n次,最少出现1次嘛,假设最大次数是mid,有这样的数就是 b[i]/mid 的和。(b[i]是桶排序之后的),还是那个看是否符合条件,这也是二分的思想。先假设出一个解,再找是否符合条件,一直二分就找到了临界值。
知道了出现次数,数又从1开始,按这个数出现次数 / 上一阶段求出的次数 就可以知道这个数是否存在且重复 ,找出前k个数就好啦。(因为可能有多个符合条件的序列,只要输出一个就好,所以我们从1开始,找到k个数就结束,不管后面的啦)
代码倒是挺简单的,我都说这么多,应该就好写了,但是中间二分找次数的思想,以及找是否存在或重复的方法都需要理解并记住鸭
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 int a[300000], b[300000], n, k,c[300000],cnt=0; 9 bool can(int aa) 10 { 11 int ans = 0; 12 for (int i = 1; i <= 200000; i++) 13 ans += b[i] / aa; 14 if (ans >= k) return 1; 15 else return 0; 16 } 17 int main() 18 { 19 cin >> n >> k; 20 for (int i = 1; i <= n; i++) 21 { 22 cin >> a[i]; 23 b[a[i]]++; 24 } 25 int l = 1, r = n; 26 while (l+1< r) 27 { 28 int mid = (l + r) / 2; 29 if (can(mid)) l = mid; 30 else r = mid-1; 31 } 32 for (int i = 1; i <= 200000; i++) 33 for (int j = 1; j <= b[i] / l; j++) 34 if (cnt < k) 35 c[++cnt] = i; 36 for (int i = 1; i < cnt; i++) 37 cout << c[i] << " "; 38 cout << c[cnt] << endl; 39 return 0; 40 }
E:Thematic Contests
Description
Polycarp has prepared nn competitive programming problems. The topic of the ii-th problem is aiai, and some problems' topics may coincide.
Polycarp has to host several thematic contests. All problems in each contest should have the same topic, and all contests should have pairwise distinct topics. He may not use all the problems. It is possible that there are no contests for some topics.
Polycarp wants to host competitions on consecutive days, one contest per day. Polycarp wants to host a set of contests in such a way that:
- number of problems in each contest is exactly twice as much as in the previous contest (one day ago), the first contest can contain arbitrary number of problems;
- the total number of problems in all the contests should be maximized.
Your task is to calculate the maximum number of problems in the set of thematic contests. Note, that you should not maximize the number of contests.
Input
The first line of the input contains one integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the number of problems Polycarp has prepared.
The second line of the input contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109) where aiai is the topic of the ii-th problem.
Output
Examples
Input
18
2 1 2 10 2 10 10 2 2 1 10 10 10 10 1 1 10 10
Output
14
Input
10
6 6 6 3 6 1000000000 3 3 6 6
Output
9
Input
3
1337 1337 1337
Output
3
Hint
In the first example the optimal sequence of contests is: 22 problems of the topic 11, 44 problems of the topic 22, 88 problems of the topic 1010.
In the second example the optimal sequence of contests is: 33 problems of the topic 33, 66problems of the topic 66.
In the third example you can take all the problems with the topic 13371337 (the number of such problems is 33 so the answer is 33) and host a single contest.
正确解法:
首先是桶排序,题目的意思是一样的数的个数 能形成 以2为d 的等比数列的和的最大值。
其实跟这个数没关系,但跟这个数出现的次数有关,就成了桶排序,可是十亿的数组没办法开数组,全局变量也不可以。
所有人都用map啊,可我不会map啊。
统计过数出现的次数后,从小到大排序。然后从1开始遍历,到2*105 总共有2*105个数,万一数都一样呢。
这题目所说的是 1.2.6 中可以成为1.2.4 ans=7. 1.3.6 可以成为1.2.4 也可以 3.6 ans=9,求最大的。
从1开始遍历,二分找出第一个大于1的下标。然后答案加上1,1变成2,二分找出第一个大于2的下标,直到走到数据的最大值。
要注意的是,数据的n+1是0,那么这个数不存在,lower—bound()就会返回n+1.
啊啊啊我研究的答案是用一个数来存上一个数的下标+1,这个数的下标=max(下标,上个数的下标+1)
刚开始以为所有的数都小于这个数时,二分lower 就会返回n+1,直接就break了,还要存上一个数的下标有什么用呢。
后来提交错了,才发现这是害怕这个数即大于1,也大于2.那么这个数就加了两次,我们是不允许这样存在的。
于是这个数的下标必须大于等于上个数的下标+1.
啊说的乱七八糟自己都不知道自己在说什么。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<string> 6 #include<cstring> 7 #include<map>//map头文件 8 using namespace std; 9 int cc[300010], cnt = 0; 10 int solver(int f) 11 { 12 int ans = 0,ps=0;//ps存上一个数的下标,所以初始为0. 13 while (true) 14 { 15 int id = lower_bound(cc + 1, cc + cnt + 1, f)-cc;//注意二分函数的用法,最后要减去数组 16 id = max(id,ps+1); 17 if (id > cnt) break; 18 ans += f; 19 f = f * 2; 20 ps = id; 21 } 22 return ans; 23 } 24 int main() 25 { 26 int a, n,aaa=0; 27 map<int, int>M;//map申请一个数组 28 cin >> n; 29 for (int i = 1; i <= n; i++) 30 { 31 cin >> a; 32 M[a]++; 33 } 34 map<int, int>::iterator it;//不知道有什么用,map的基本用法吧 35 for (it = M.begin(); it != M.end(); it++) 36 cc[++cnt] = it->second;//第一个数first是下标,第二个数second是这个数 37 sort(cc + 1, cc + cnt + 1); 38 for (int i = 1; i <= 200000; i++) 39 aaa = max(aaa,solver(i)); 40 cout << aaa << endl; 41 return 0; 42 }
F1:Pictures with Kittens
Description
Vova likes pictures with kittens. The news feed in the social network he uses can be represented as an array of nn consecutive pictures (with kittens, of course). Vova likes all these pictures, but some are more beautiful than the others: the ii-th picture has beauty aiai.
Vova wants to repost exactly xx pictures in such a way that:
- each segment of the news feed of at least kk consecutive pictures has at least one picture reposted by Vova;
- the sum of beauty values of reposted pictures is maximum possible.
For example, if k=1k=1 then Vova has to repost all the pictures in the news feed. If k=2k=2 then Vova can skip some pictures, but between every pair of consecutive pictures Vova has to repost at least one of them.
Your task is to calculate the maximum possible sum of values of reposted pictures if Vova follows conditions described above, or say that there is no way to satisfy all conditions.
Input
The first line of the input contains three integers n,kn,k and xx (1≤k,x≤n≤2001≤k,x≤n≤200) — the number of pictures in the news feed, the minimum length of segment with at least one repost in it and the number of pictures Vova is ready to repost.
The second line of the input contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109), where aiai is the beauty of the ii-th picture.
Output
Print -1 if there is no way to repost some pictures to satisfy all the conditions in the problem statement.
Otherwise print one integer — the maximum sum of values of reposted pictures if Vova follows conditions described in the problem statement.
Examples
Input
5 2 3
5 1 3 10 1
Output
18
Input
6 1 5
10 30 30 70 10 10
Output
-1
Input
4 3 1
1 100 1 1
Output
100
正确解法:
DP。d[i][j] d[i][j]d[i][j]表示前i ii个数中,在选了ai
的情况下,总共选择了j jj个数的最大值。
则有d[i][j]=max(d[y][j−1]+a[i]),(i−k≤y) d[i][j]=max(d[y][j-1]+a[i]),(i-k\le y)d[i][j]=max(d[y][j−1]+a[i]),(i−k≤y)
最后的答案=max(d[i][x]),(n−k+1≤i) =max(d[i][x]),(n-k+1\le i)=max(d[i][x]),(n−k+1≤i)
其中可以发现转移的部分:d[i][j]=max(d[y][j−1]+a[i]),(i−k≤y) d[i][j]=max(d[y][j-1]+a[i]),(i-k\le y)d[i][j]=max(d[y][j−1]+a[i]),(i−k≤y)
是求d[y][j−1] d[y][j-1]d[y][j−1],y yy在区间[i−k,i−1] [i-k,i-1][i−k,i−1]的最大值,于是可以构造一个单调递减的栈优化DP。
不会DP,先找别人的题解看一下qaq
1 #include <iostream> 2 #include <string> 3 #include <complex> 4 #include <math.h> 5 #include <set> 6 #include <vector> 7 #include <map> 8 #include <queue> 9 #include <stdio.h> 10 #include <stack> 11 #include <algorithm> 12 #include <list> 13 #include <ctime> 14 15 #include <memory.h> 16 #include <assert.h> 17 18 #define y0 sdkfaslhagaklsldk 19 20 #define y1 aasdfasdfasdf 21 #define yn askfhwqriuperikldjk 22 #define j1 assdgsdgasghsf 23 #define tm sdfjahlfasfh 24 #define lr asgasgash 25 #define norm asdfasdgasdgsd 26 #define have adsgagshdshfhds 27 #define ends asdgahhfdsfshdshfd 28 #define prev asdgSHJsfgsdfhdsh 29 #define hash asdgasdgasdgdfrywewery 30 31 #define eps 1e-8 32 #define M_PI 3.141592653589793 33 #define bsize 512 34 35 #define ldouble long double 36 using namespace std; 37 38 #define bs 1000000007 39 40 const int N = 300031; 41 42 int n,k,x,ar[5031]; 43 44 long long dp[5031][5031]; 45 46 int L[5031]; 47 48 long long sparse[20][5031]; 49 50 long long get(int l,int r){ 51 int span=r-l+1; 52 span=L[span]; 53 return max(sparse[span][l],sparse[span][r-(1<<span)+1]); 54 } 55 56 void build_sparse(int lev){ 57 for (int i=1;i<=n;i++){ 58 sparse[0][i]=dp[lev][i]; 59 } 60 for (int lev=1;lev<15;lev++){ 61 for (int i=1;i+(1<<lev)-1<=n;i++){ 62 sparse[lev][i]=max(sparse[lev-1][i],sparse[lev-1][i+(1<<lev)/2]); 63 } 64 } 65 } 66 67 int main(){ 68 // freopen("apache.in","r",stdin); 69 // freopen("apache.out","w",stdout); 70 // freopen("input.txt", "r", stdin); 71 // freopen("output.txt", "w", stdout); 72 ios_base::sync_with_stdio(0); 73 //cin.tie(0); 74 75 for (int i=2;i<=5000;i++){ 76 L[i]=L[i/2]+1; 77 } 78 79 cin>>n>>k>>x; 80 for (int i=1;i<=n;i++){ 81 cin>>ar[i]; 82 } 83 84 for (int lev=1;lev<=x;lev++){ 85 for (int i=1;i<=n;i++){ 86 dp[lev][i]=-1e18; 87 } 88 } 89 90 for (int i=1;i<=k;i++){ 91 dp[1][i]=ar[i]; 92 } 93 94 for (int lev=2;lev<=x;lev++){ 95 96 build_sparse(lev-1); 97 for (int i=2;i<=n;i++){ 98 int ps=max(1,i-k); 99 // cout<<ps<<" "<<i-1<<" "<<get(ps,i-1)<<endl; 100 dp[lev][i]=get(ps,i-1)+ar[i]; 101 } 102 } 103 104 long long ans=-1e18; 105 for (int i=n-k+1;i<=n;i++){ 106 ans=max(ans,dp[x][i]); 107 } 108 109 if (ans<0) 110 ans=-1; 111 112 cout<<ans<<endl; 113 114 // cin.get(); cin.get(); 115 return 0; 116 }