Codeforces Round #611Div3
作者:互联网
Codeforces Round #611Div3 解题报告
A. Minutes Before the New Year
- 直接模拟
#include<bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
typedef long long ll;
int T, n;
void solve()
{
int h, m;
cin >> h >> m;
int ans = 0;
ans += (24 - h - 1) * 60;
ans += (60 - m);
cout << ans << endl;
}
int main()
{
scanf("%d", &T);
while(T--) solve();
return 0;
}
B. Candies Division
- 平分是最好的方案,做不到就往多里加,贪心。
#include<bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
typedef long long ll;
int T, n, k;
void solve()
{
cin >> n >> k;
if(n%k == 0){
cout << n << endl;
return;
}
int a = n / k; //每个人a个糖
int b = n % k;
if(b <= k / 2) cout << a*k+b << endl;
else cout << a*k + k / 2 << endl;
}
int main()
{
scanf("%d", &T);
while(T--) solve();
return 0;
}
C. Friends and Gifts
- 其实题目本意就是让你在序列为0的地方填数字,然后让得到的序列为一个排列,且对应位置上不能出现对应数字。
- 只需要记录一下哪些数字没出现,之后倒序往里头填就行了。
- 比如说5 0 0 2 4中1和3没有出现过 ,之后倒着填就是5 3 1 2 4。
- 但是可能会有出现位置和数字重合的状况,也就是\(a(i)==i\),但也可以发现如果倒序填的话只会有一个位置出现这样的情况,加上一定会出现两个0,交换一下就好了。
#include<bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int n, a[maxn];
int vis[maxn];
vector<int> z;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
vis[a[i]] = 1;
if(a[i] == 0) z.push_back(i);
}
int cnt = 1;
for(int i = n; i >= 1; i--)
{
if(a[i]) continue;
while(vis[cnt]) cnt++;
a[i] = cnt; vis[cnt] = 1;
}
for(int i = 0; i < z.size(); i++)
{
int num = z[i];
if(a[num] == num)
{
if(i < z.size()-1) swap(a[num], a[z[i+1]]);
else swap(a[num], a[z[i-1]]);
break;
}
}
for(int i = 1; i <= n; i++)
printf("%d ", a[i]);
return 0;
}
D. Christmas Trees
- 贪心。
- 首先肯定是放在圣诞树左右两边是最好的选择。
- 输入的将位置放入一个queue中。
- 然后类似于bfs的思路遍历点的左右即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
queue<int> q;
map<int, int> mp;
int n, m;
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 1, x; i <= n; i++)
{
cin >> x;
q.push(x); mp[x] = 0;
}
long long res = 0;
vector<int> ans;
while(m)
{
int p = q.front(); q.pop();
if(!mp.count(p-1))
{
q.push(p-1);
mp[p-1] = mp[p]+1;
}
if(!mp.count(p+1))
{
q.push(p+1);
mp[p+1] = mp[p]+1;
}
if(mp[p] > 0)
{
ans.push_back(p);
res += mp[p];
m--;
}
}
cout << res << endl;
for(auto x : ans)
cout << x << " ";
puts("");
return 0;
}
E. New Year Parties
- 这一题我的代码很丑,但也比较好明白。
- 其实只要贪心挪动就行了。
- 最小:
- 如果上一个位置有人,那我就挪到上一个位置。
- 否则如果下一个位置有人,我就挪到下一个位置上,同时这个位置就不能再移动了。
- 如果下一个位置没有人但是下下个位置有人,就可以一起挪动到中间的位置。
- 最大:
- 如果一个位置有三个人,就占领三个位置。
- 如果两个人,且上一个位置没有人,就占领前面和当前位置,否则占领当前位置和后一个位置。
- 如果只有一个人,看前后站人的情况。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int a[maxn], n;
int vis[maxn];
int vis1[maxn];
int vis2[maxn];
bool mi[maxn];
void get_min()
{
for(int i = 1; i <= n; i++)
{
if(vis1[i] && !mi[i])
{
if(vis1[i-1])
{
vis1[i-1] += vis1[i];
vis1[i] = 0;
mi[i-1] = 1;
}
else if(vis1[i+1])
{
vis1[i+1] += vis1[i];
vis1[i] = 0;
mi[i+1] = 1;
}
else if(vis1[i+2] && !mi[i+2])
{
vis1[i+1] += vis1[i+2];
vis1[i+1] += vis1[i];
vis1[i] = vis1[i+2] = 0;
mi[i+1] = mi[i] = mi[i+2] = 1;
}
}
} int ans = 0;
for(int i = 0; i <= n+1; i++)
if(vis1[i]) ans++;
cout << ans << " ";
}
void get_max()
{
for(int i = 1; i <= n; i++)
{
if(vis[i])
{
int num = vis[i];
if(num >= 3)
{
vis2[i-1]++;
vis2[i]++;
vis2[i+1]++;
}
else if(num == 2)
{
//如果上一个位置没有放
if(!vis2[i-1])
{
vis2[i-1]++;
vis2[i]++;
}
else {
vis2[i]++;
vis2[i+1]++;
}
}
else if(num == 1)
{
if(!vis2[i-1]) vis2[i-1]++;
else if(!vis2[i]) vis2[i]++;
else vis2[i+1]++;
}
}
}
int ans = 0;
for(int i = 0; i <= n+1; i++)
if(vis2[i]) ans++;
cout << ans << endl;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
vis[a[i]]++;
vis1[a[i]]++;
}
get_min();
get_max();
return 0;
}
F. DIY Garland
题意描述
- 给定\(n-1\)条线和\(n\)座灯。
有一个灯是源灯,所有电都从这来。
- 一跟电线连接两个灯,每个灯有自己的编号,亮度为\(2^i\)。
- 灯分为主灯和副灯,电源从主灯来,流向副灯。
- 每条电线的重要程度为切断这个电线之后不能通电的亮度之和。
按照电线的重要性从大到小给出了\(n-1\)条线的主灯编号,让你从大到小输出每条电线连接的两个灯的序号。
思路
- 好麻烦的题面...
- 首先\(n-1\)条线和\(n\)座灯,可以确定这个结构是一棵树。
- 题目按照电线重要性给出了节点的主灯,那么第一个必然是源灯,因为连接源灯的电线重要性肯定最大。
- 其次叶子节点一定不是主灯,而且我们知道叶子节点的子树大小为0。(用\(deg\)数组记录子树大小)
- 所以我们可以先找出所有的叶子节点压入优先队列,之后倒序连接主灯。(因为电线的重要程度是从大到小给出的)。
- 连接之后将其看成一体,这样主灯子树大小就可以减一了。
- 当主灯的子树大小减为0时,就变成了叶子节点,加入队列;如此循环往复直到形成一棵树。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int deg[maxn], n, rt;
vector<int> main_lamp;
int main()
{
scanf("%d", &n);
scanf("%d", &rt);
deg[rt]++;
main_lamp.push_back(rt);
for(int i = 2, x; i <= n - 1; i++)
{
scanf("%d", &x);
deg[x]++;
main_lamp.push_back(x);
}
priority_queue<int, vector<int>, greater<int> > q;
for(int i = 1; i <= n; i++)
if(deg[i] == 0) q.push(i);
vector<pair<int, int> > ans;
while(q.size())
{
int x = q.top();
q.pop();
int y = main_lamp[main_lamp.size()-1];
main_lamp.pop_back();
ans.push_back(make_pair(y, x));
if(ans.size() == n - 1) break;
deg[y]--;
if(deg[y] == 0) q.push(y);
}
cout << rt << endl;
for(int i = ans.size()-1; i >= 0; i--)
cout << ans[i].first << " " << ans[i].second << endl;
return 0;
}
标签:vis2,int,Codeforces,long,++,maxn,mp,611Div3,Round 来源: https://www.cnblogs.com/zxytxdy/p/12163896.html