标签:+= 存储 nod define 构造 its i++ 移动 turn
F
题意:给你n-1边,n个灯,每个边连着两颗灯,有主,次灯区别,电流由主到次,每条边有一个特性,取消这条边后n个灯不能亮的值(每个灯亮值为2^i,灯编号i),由特性值由大到小给出每条边的主灯,求出每对主灯次灯。
题解:可知是一棵树,排第一个的肯定是原点,即根。然后没出现的肯定是叶子节点,我们遍历一遍求出叶子节点,然后我们知道灯亮与编号有关,所以我们由将叶子节点放入优先队列,叶子节点从小到大与主灯从小到大匹配,当主灯中的cnt【i】为0,说明他已经没有子树,也就是他也是一颗“叶子节点了”
就放入优先队列中继续匹配。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
priority_queue<int,vector<int>,greater<int> >pq;
int k,n,x[maxn],vis[maxn],cnt[maxn];
vector<pair<int,int> >G;
int main()
{
cin>>n;
int tot=n-1;
for(int i=1;i<n;i++){
cin>>x[i];
vis[x[i]]=1;
cnt[x[i]]++;
}
printf("%d\n",x[1]);
for(int i=1;i<=n;i++){
if(!vis[i]) pq.push(i);
}
while(1){
if(tot==0) break;
int now=pq.top();pq.pop();
int res=x[tot];tot--;
G.push_back(make_pair(res,now));
cnt[res]--;
if(cnt[res]==0) pq.push(res);
}
int sz=G.size();
for(int i=0;i<sz;i++){
printf("%d %d\n",G[i].first,G[i].second);
}
}
题意:每个人可以出现三个操作,将自己呆在原地,或向右移动一距离或向左。
求最大占用地方块数和最小的占用地方块数。
分析:最多就是尽可能得让所有房子都有人嘛,最少就是尽可能得集中这些人。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+7;
int x[maxn],n,xx,xxx[maxn];
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> xx, x[xx]++, xxx[xx]++;
for (int i = n + 1; i >= 1; i--) {
if (x[i] > 1) {
x[i - 1]++;
x[i]--;
}
}
for (int i = 0; i <= n; i++) {
if (x[i] > 1) {
x[i + 1]++;
x[i]--;
}
}
int most = 0;
for (int i = 0; i <= n + 1; i++) {
if (x[i]) most++;
}
int least = 0;
for (int i = 1; i <= n + 1;) {
if (xxx[i]) {
i += 3;
least++;
} else {
i++;
}
}
cout << least << " " << most << endl;
return 0;
}
D.Christmas Trees
题目大意:给定n个不同的整数点,让你找m个不同的整数点,使得这m个点到到这n个点最小距离之和最小。
分析:对于每个点,肯定是先选取距离为1的,然后再选取距离为2的,以此类推。但是有的点不一定选得到,因此我们可以用队列来存储那些可以到达的点,这样就可以得知这个题跑个bfs可行。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int n,m,a[maxn];
vector<int>G;
ll ans;
map<int,bool>vis;
struct node
{
int pos,len;
};
queue<node>q;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
vis[a[i]]=1;
}
for(int i=1;i<=n;i++){
if(vis[a[i]-1]==0) q.push(node{a[i]-1,1}),vis[a[i]-1]=1;
if(vis[a[i]+1]==0) q.push(node{a[i]+1,1}),vis[a[i]+1]=1;
}
while(m--){
node res=q.front();q.pop();
int u=res.pos,v=res.len;
G.push_back(u);
ans+=v;
if(vis[u-1]==0){
q.push(node{u-1,v+1});
vis[u-1]=1;
}
if(vis[u+1]==0){
q.push(node{u+1,v+1});
vis[u+1]=1;
}
}
printf("%lld\n",ans);
int sz=G.size();
for(int i=0;i<sz;i++){
if(i)printf(" %d",G[i]);
else printf("%d",G[i]);
}
puts("");
return 0;
}
题目大意:每个人都要给其他一个人一个礼物,并且每个人都要收到一个礼物。请你构造一种合法的赠送礼物的方法,使得每个人都赠送非自己的人一个礼物,并且从其他人那里收到一个礼物。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef vector<VI> VII;
typedef vector<VII> VIII;
typedef pair<int, int> PII;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
const int N = 2e5 + 5;
const ll MOD = 1e9 + 7;
int flag[N];
int give[N];
int gett[N];
queue<int> Q;
int num = 0;
int main()
{
int n;
scanf("%d", &n);
rep(i,1,n)
{
int x;
scanf("%d", &x);
flag[i] = x;
give[i] = x;
if(x != 0)
gett[x] = i;
else
num ++;
}
rep(i,1,n)
{
if(gett[i] == 0)
Q.push(i);
}
int pos = 1;
rep(i,1,n)
{
if(give[i] == 0)
{
pos = i;
while(give[pos] == 0)
{
give[pos] = Q.front();
Q.pop();
if(pos == give[pos])
{
Q.push(pos);
give[pos] = Q.front();
Q.pop();
}
pos = give[pos];
num --;
}
}
}
rep(i,1,n)
{
if(give[i] == i)
{
rep(j,1,n)
{
if(flag[j] == 0)
{
swap(give[i], give[j]);
break;
}
}
}
}
rep(i,1,n)
{
printf("%d ", give[i]);
}
printf("\n");
return 0;
}
Codeforces Round #611 (Div. 3)
标签:+= 存储 nod define 构造 its i++ 移动 turn
原文地址:https://www.cnblogs.com/hgangang/p/12237328.html