码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #611 (Div. 3)

时间:2020-01-28 09:18:59      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:+=   存储   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);
    }
}

  

E

题意:每个人可以出现三个操作,将自己呆在原地,或向右移动一距离或向左。

求最大占用地方块数和最小的占用地方块数。

分析:最多就是尽可能得让所有房子都有人嘛,最少就是尽可能得集中这些人。

代码:

#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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!