题目在这里
D - Candy Box (easy version)
题意:给出n颗糖果分别的种类号,求出在每种糖果取出的个数不同的情况下,最多能取出多少个糖果。
思路:先统计出每种糖果的个数,然后从大到小排序:
-----------eg. 2 2 1 1 1 1
则可以取出 2 1 0 0 0 0 (共3个糖果)
从最多的糖果开始取,然后依次取min(前一种糖果取的个数-1,当前糖果个数)。
注:如果使用memset会超时,所以不要全部初始化,初始化一部分(1~n)就行。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
bool cmp(int a,int b)
{
return a > b;
}
int a[200005];
int b[200005];
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
//memset(a,0,sizeof(a));
//memset(b,0,sizeof(b));
cin>>n;
for(int i=0;i<=n;i++){
a[i]=0;
}
for(int i=0;i<=n;i++){
b[i]=0;
}
for(int i = 1;i <= n;i++)
{
cin>>a[i];
}
sort(a+1,a+n+1);
int cnt = 1;
int tmp = a[1];
for(int i = 1;i <= n;i++)
{
if(a[i] == tmp)
{
b[cnt]++;
}else
{
tmp = a[i];
cnt++;
b[cnt]++;
}
}
if(b[cnt] == 0) cnt--;
sort(b+1,b+cnt+1,cmp);
int now = b[1];
int ans = 0;
for(int i = 1;i <= cnt;i++)
{
ans += now;
now = max(0,min(now-1,b[i+1]));
}
printf("%d\n",ans);
}
return 0;
}
G - Candy Box (hard version)
题意:在优先糖果个数最多的情况下,优先喜爱数。最后输出该种情况的糖果个数和喜爱数。
思路:利用优先队列,用结构体存储两个变量:该种糖果的个数和喜爱数。然后循环扫描优先队列,取出头结点,如果后面的糖果个数和当前种类的糖果个数一样,那么个数–,且若喜爱数和个数一样,喜爱数也减一。
注:每个test初始化的时候,不能直接memset,要初始化该次test使用了的位置。故也要开一个数组mp[i],记录糖果种类。eg. a[1] = 2,a[2] = 5…,a[n] = 12。即,有2号种类糖果、5号、…、12号种类糖果。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
struct node {
int cnt, like;
bool operator < (const node &x) const {
if (cnt == x.cnt) return like < x.like;
else return cnt < x.cnt;
}
};
int c[N], l[N];
int main() {
int T; cin >> T;
while (T--) {
int n; scanf("%d", &n);
map<int, int> mp;
for (int i = 0; i < n; i++) {
int t1, t2; scanf("%d%d", &t1, &t2);
c[t1]++;
if (t2) l[t1]++;
mp[t1] = 1;
}
priority_queue<node> que;
for (auto it : mp) {
int i = it.first;
if (c[i]) {
node t;
t.cnt = c[i]; t.like = l[i];
que.push(t);
}
}
int maxn = que.top().cnt - 1;
int anscnt = que.top().cnt, anslike = que.top().like;
que.pop();
while(maxn > 0 && !que.empty()) {
node t = que.top(); que.pop();
if (t.cnt > maxn) {
t.cnt = maxn;
t.like = min(t.like, t.cnt);
que.push(t);
continue;
}
anscnt += t.cnt;
anslike += t.like;
maxn = t.cnt - 1;
}
cout << anscnt << ' ' << anslike << endl;
for (auto it : mp) {
int i = it.first;
c[i] = 0; l[i] = 0;
}
}
return 0;
}
E - Subsequences (easy version)
题意:给出一串字符串s,和容器的容量k,让你从s中挑选出k个不同的子序列(包括“ ”),最后输出最少花费,如果挑不出k个,则输出“-1”。
思路:bfs,将初始字符串入队,然后循环每减去一个字符且set中没有出现过该新字符串则加入set和队中。直到满足size >= k或队列为空时结束。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <set>
using namespace std;
string st;
int n,k;
queue <string> q;
set <string> s;
void bfs()
{
q.push(st);
s.insert(st);
while(!q.empty())
{
string dd=q.front();
q.pop();
for(int i=0 ; i<dd.size() ; i++)
{
string s1=dd;
s1.erase(i,1);
if(!s.count(s1)&&s.size()+1<=k)
{
q.push(s1);
s.insert(s1);
}
}
}
}
int main()
{
cin>>n>>k;
cin>>st;
bfs();
if(s.size()<k)
{
cout<<"-1"<<endl;
return 0;
}
int ans=0;
for(auto i :s)
{
ans += (st.length()-i.length());
}
cout<<ans<<endl;
return 0;
}