2019.10.21 星期一
考试一股脑安排在秋假前,扎扎实实考到秋假放假那一刻,真的是站好最后一班岗哦。不过没啥说的,拿出劲儿干就是了。
今天打了codeforce div3,以前认为codeforces div3很好打,我错了,真的不好打,今天这几道一道贪心,一道二分,一道模拟,都挺抽象的,我要不是专门做过kuangbin的练习可能还真不会想到那么抽象的解法。不多说了,看题吧,四道题的题解在这里。
codeforces round 570, div3(传送门)
A题 Nearest Integer Number 这道题大眼一扫就知道怎么写了,不多说,暴力尝试
#include <bits/stdc++.h>
using namespace std;
#define limit 3000 + 5//防止溢出
#define INF 0x3f3f3f3f3f
#define inf 1<<20
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define ff(a) printf("%d\n",a );
#define MOD 1e9 + 7
typedef long long ll;
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}//快读
int kase, n;
int isLegal(int num){
ll ans = 0;
while(num){
ans += num % 10;
num /= 10;
}
return ans % 4 == 0;
}
int main(){
//freopen("C:\\Users\\administrator01\\CLionProjects\\untitled14\\data.txt", "rt" , stdin);
scanf("%d", &n);
for(int i = 0 ; i <= 10 ; ++i){
if(isLegal(n + i)){
printf("%d" , n + i);
break;
}
}
return 0;
}
B题 Equalize Price 这道题输入量很大,用枚举和暴搜一定会超时,不过这个区间上下浮动让我想到了雷达和掉落固定杆子那道题,可以具象化为贪心求区间重合+最大右端点,重载操作符是重中之重,这里看代码吧。
#include <bits/stdc++.h>
using namespace std;
#define limit 3000 + 5//防止溢出
#define INF 0x3f3f3f3f3f
#define inf 1<<20
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define ff(a) printf("%d\n",a );
#define MOD 1e9 + 7
typedef long long ll;
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}//快读
int kase, n;
int m;
struct edge{
int vs ,ve;
edge(int ss = 0, int ee = 0):vs(ss) , ve(ee){}
bool operator<(const edge &rhs)const{
if(vs == rhs.vs){
return ve > rhs.ve;
}
return vs < rhs.vs;
}
};
int main(){
//freopen("C:\\Users\\administrator01\\CLionProjects\\untitled14\\data.txt", "rt" , stdin);
scanf("%d" , &kase);
while(kase--){
vector<edge>v;
scanf("%d%d" , &n, &m);
for(int i = 0 ; i < n ; ++i){
int val;
scanf("%d" , &val);
v.push_back(edge(val - m, val + m));
}
sort(v.begin() , v.end());
int ans = 0;
int last = v[0].ve;
int flag = 1;
int highest = 0;
for(int i = 1 ; i < v.size() ; ++i){
if(last < v[i].vs){
last = v[i].vs;
flag = 0;
break;
}
}
if(flag){
printf("%d\n", v[0].ve);
}else{
printf("%d\n", -1);
}
}
return 0;
}
C题 Computer Game, 这道题有好多种办法,看不少同志是O(1)的算法,不过我的想法是用二分,关键结论是在m次游戏之后还剩下大于b的电量,由于区间满足二分的性质,所以上二分搜索,然后judge内容由结论推出,不难,看吧。
#include <bits/stdc++.h>
using namespace std;
#define limit 3000 + 5//防止溢出
#define INF 0x3f3f3f3f3f
#define inf 1<<20
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define ff(a) printf("%d\n",a );
#define MOD 1e9 + 7
typedef long long ll;
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}//快读
ll n ,m , a, b;
bool judge(ll i){
return n - ((i * a) + (m - i) * b) > 0;
}
int main(){
//freopen("C:\\Users\\administrator01\\CLionProjects\\untitled14\\data.txt", "rt" , stdin);
int t;
scanf("%d" , &t);
while(t--){
scanf("%lld%lld%lld%lld" , &n , &m ,&a, &b);
ll L = 0 , R = m;
ll ans = 0;
while(L <= R){
ll mid = L + (R - L) / 2;
if(judge(mid)){
ans = mid;
L = mid + 1;
}else{
R = mid - 1;
}
}//二分求解
if(judge(ans))
printf("%lld\n",ans);
else
printf("%d\n" , -1);
}
return 0;
}
D题,Candy Box (Easy)这道题也不难,就是模拟,我发现出题人是不是不知道有set和map这种stl结构,这道题说的是贪心和dp,但是我没发现任何上dp的必要,用map记出现次数,或者是multimap也行,然后从最高频率的开始枚举,如果拿不完,那就拿之后的就好了,一个map一个set搞定
#include <bits/stdc++.h>
using namespace std;
#define limit 3000 + 5//防止溢出
#define INF 0x3f3f3f3f3f
#define inf 1<<20
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define ff(a) printf("%d\n",a );
#define MOD 1e9 + 7
typedef long long ll;
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}//快读
int kase , n;
struct Node{
int num, times;
Node(int nn, int tt):num(nn), times(tt){}
bool operator<(const Node &rhs)const{
return times > rhs.times;
}
};
int main(){
//freopen("C:\\Users\\administrator01\\CLionProjects\\untitled14\\data.txt", "rt" , stdin);
scanf("%d" , &kase);
while(kase--){
scanf("%d" , &n);
map<int ,int>s;
set<int>sett;
for(int i = 0 ; i < n; ++i){
int val;
scanf("%d" , &val);
++s[val];//增加数量
}
for(auto it = s.begin(); it != s.end() ; ++it){
int val = it->second;
while(sett.find(val) != sett.end() && val){
--val;
}
sett.insert(val);
}
int ans = 0;
for(auto it = sett.begin() ; it != sett.end() ; ++it){
ans += *it;
}
printf("%d\n", ans);
}
return 0;
}