Codeforces Round #592 (Div. 2)

A. Pens and Pencils (CF 1244 A)

题目大意

给定\(a,b,c,d,k\),问是否\(\lceil \dfrac{a}{c} \rceil + \lceil \dfrac{b}{d} \rceil \leq k\)

解题思路

快速读懂题意即可。

神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int main(void) {
    int kase; read(kase);
    for (int i = 1; i <= kase; i++) {
        int a,b,c,d,k;
        read(a);
        read(b);
        read(c);
        read(d);
        read(k);
        int qaq=ceil(a*1.0/c);
        int qwq=ceil(b*1.0/d);
        if (qaq+qwq>k) puts("-1");
        else printf("%d %d\n",qaq,qwq);
    }
    return 0;
}


B. Rooms and Staircases (CF 1244 B)

题目大意

两层楼,每层楼有\(n\)个房间,相邻房间之间有门互通,一楼的某些房间与二楼的对应房间有楼梯连接。问从哪里出发,在不重复经过一个房间的情况下,经过的房间数最多。输出这个最多的房间数。

解题思路

如果没有楼梯,答案显然是\(n\),如果有一个楼梯,那么答案就是\(n+1\)或者\(2*s\)或者\(2*(n-s+1)\)\(s\)是楼梯所在的房间编号。很显然答案是在后两者。如果有多个楼梯,由于经过的房间不能再走,那么答案就是\(n+num\)或者\(2*s\)或者\(2*(n-s+1)\)\(num\)是楼梯数量,由于\(num\leq n\),答案还是在后两者,即只用一个楼梯的情况。我们枚举经过的楼梯分别计算答案取最大值即可。

神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int main(void) {
    int kase; read(kase);
    for (int i = 1; i <= kase; i++) {
        int n;
        read(n);
        char s[n+1];
        scanf("%s",s);
        int ans=n;
        for(int i=0;i<n;++i)
            if (s[i]=='1') ans=max(ans,max(2*(i+1),2*(n-i)));
        write(ans,'\n');
    }
    return 0;
}


C. The Football Season (CF 1244 C)

题目大意

给定\(n,p,w,d\),要求找到一个可行非负整数解\(x,y,z\),满足\(x \cdot w + y \cdot d = p\)\(x + y + z = n\)。其中\(w\geq d\)

解题思路

由于\(w\geq d\),当\(y\geq w\)有解时,我们不断令\(y=y-w\)\(x=x+d\),直到\(y<w\),这样等式\(x \cdot w + y \cdot d = p\)仍然成立。而由于\(x^{'}+y^{'}=x+d+y-w<x+y\)\(x^{'}+y^{'}\)的和变小,原来有非负数解\(z\)的,此时肯定还有非负数解\(z\),而原来没有的,此时可能会有。故而我们只要枚举\(y\)\(0\)\(w-1\)即可。

神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int main(void) {
    LL n,p,w,d;
    read(n);
    read(p);
    read(w);
    read(d);
    LL x=-1,y=-1,z=-1;
    for(y=0;y<w;++y){
        if ((p-y*d)%w==0){
            x=(p-y*d)/w;
            z=n-x-y;
            break;
        }
    }
    if (x<0||y<0||z<0) puts("-1");
    else printf("%lld %lld %lld\n",x,y,z);
    return 0;
}


D. Paint the Tree (CF 1244 D)

题目大意

给树的点染色,有三种颜色。已知每个点的每种颜色的染色费用,求一种染色方案,使得任意相邻的三个点颜色各不相同,且费用最小。不存在该方案输出\(-1\)

解题思路

我们会发现一个重要性质:存在染色方案的树一定是条链。这样枚举了前两个点的颜色,剩下点的颜色都确定了。一共六种情况扫一遍即可。

神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

LL ans=1e16;;

void DFS(int n,int fa,int x,int a,int b,int c,LL qwq,vector<int>edge[],LL cost[][3],int cnt[],int color[],int best_color[]){
    qwq+=cost[x][a];
    color[x]=a;
    if (x!=fa&&cnt[x]==1){
        if (ans>qwq) {
            ans=qwq;
            for(int i=1;i<=n;++i) best_color[i]=color[i];
        }
        return;
    }
    for(auto i:edge[x]){
        if (i==fa) continue;
        if (b==-1) 
            for(int k=0;k<3;++k){
                if (k==a) continue;
                DFS(n,x,i,k,a,b,qwq,edge,cost,cnt,color,best_color);
            }
        else {
            int k=3-a-b;
            DFS(n,x,i,k,a,b,qwq,edge,cost,cnt,color,best_color);
        }
    }
}

int main(void) {
    int n;
    read(n);
    LL cost[n+1][3]={0};
    for(int i=0;i<3;++i) 
        for (int j=1;j<=n;++j)
            read(cost[j][i]);
    int cnt[n+1]={0};
    vector<int> edge[n+1];
    for(int u,v,i=1;i<n;++i){
        read(u);
        read(v);
        ++cnt[u];
        ++cnt[v];
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    int qwq=0,st=1;
    int color[n+1]={0},best_color[n+1]={0};
    for(int i=1;i<=n;++i){
        qwq+=(cnt[i]!=2);
        if (cnt[i]==1) st=i;
    }
    if (qwq!=2) puts("-1");
    else{
        DFS(n,st,st,0,-1,-1,0,edge,cost,cnt,color,best_color);
        DFS(n,st,st,1,-1,-1,0,edge,cost,cnt,color,best_color);
        DFS(n,st,st,2,-1,-1,0,edge,cost,cnt,color,best_color);
        write(ans,'\n');
        for(int i=1;i<=n;++i) printf("%d%c",best_color[i]+1,i==n?'\n':' ');
    }
    return 0;
}


E. Minimizing Difference (CF 1244 E)

题目大意

给定\(n\)个数,可以进行\(k\)次操作,每次操作选定一个数,使之加一或减一。问最终最大值与最小值的差最小是多少。

解题思路

贪心即可。每次选最大值、最小值数量最小的一个去搞。由于数很大我们离散后就可以数的个数,或者直接拿\(map\)

神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int main(void) {
    int n;
    LL k;
    read(n);
    read(k);
    map<int,LL> qwq;
    for(int u,i=1;i<=n;++i){
        read(u);
        qwq[u]++;
    }
    LL ans=qwq.rbegin()->first-qwq.begin()->first;
    while(k>0){
        if (qwq.size()==1) {ans=0; break;}
        auto st=qwq.begin();
        auto en=qwq.rbegin();
        if (st->second<en->second){
            auto st_next=st;
            st_next++;
            if (((st_next->first-st->first)*st->second)<=k){
                ans-=(st_next->first-st->first);
                k-=((st_next->first-st->first)*st->second);
                st_next->second+=st->second;
                qwq.erase(st);
            }
            else{
                LL qaq=k/st->second;
                ans-=qaq;
                k=0;
            }
        }
        else{
            auto en_before=qwq.end();
            en_before--;
            en_before--;
            if (((en->first-en_before->first)*en->second)<=k){
                ans-=(en->first-en_before->first);
                k-=((en->first-en_before->first)*en->second);
                en_before->second+=en->second;
                auto ee=qwq.end();
                --ee;
                qwq.erase(ee);
            }
            else{
                LL qaq=k/en->second;
                ans-=qaq;
                k=0;
            }
        }
    }
    write(ans,'\n');
    return 0;
}


F. Chips (CF 1244 F)

题目大意

一堆围成圆圈,初始带有黑或白颜色的芯片。有\(k\)个回合,每个回合中,如果一个芯片旁边的两个的芯片都与自己异色,则自己会变成对方的颜色。问\(k\)个回合后每个芯片的颜色。

解题思路

注意到,如果一个芯片旁边有一个芯片颜色与它一样,那么这两个芯片在整个过程中都不会变色,这些芯片我们称之为稳定芯片。在稳定芯片旁边如果有一个不稳定芯片,那么这个不稳定芯片在一个回合后变成与稳定芯片相同颜色后,也不会变色了。那就是说,对于一个圈圈来说,在两个稳定芯片之间都是不稳定的芯片,这个稳定属性会传染,两边每一个回合会传染一个芯片,使之与自己同化。而对于最终还是不稳定的芯片,由于整个过程它都在变色,那看\(k\)是奇是偶即可知道最终的颜色。\(BFS\)模拟传染过程即可。

神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int id(int x,int n){
    if (x==-1) return n-1;
    if (x==n) return 0;
    return x;
}

char change(char x){
    if (x=='W') return 'B';
    else return 'W';
}

int main(void) {
    int n,k;
    read(n);
    read(k);
    char s[n+1];
    scanf("%s",s);
    int sign[n]={0};
    for(int i=0;i<n;++i)
        if (s[i]==s[id(i-1,n)]||s[i]==s[id(i+1,n)]) sign[i]=1;
    queue<pair<pair<int,int>,int>> team;
    for(int i=0;i<n;++i) {
        if (sign[i]==1&&sign[id(i+1,n)]==0) team.push(make_pair(make_pair(i,1),0));
        if (sign[i]==1&&sign[id(i-1,n)]==0) team.push(make_pair(make_pair(i,-1),0));
    }
    while(!team.empty()){
        auto u=team.front();
        team.pop();
        if (u.second==k) continue;
        int v=id(u.first.first+u.first.second,n);
        if (sign[v]==0) {
            sign[v]=1;
            s[v]=s[u.first.first];
            team.push(make_pair(make_pair(v,u.first.second),u.second+1));
        }
    }
    bool qwq=k&1;
    for(int i=0;i<n;++i) if (sign[i]==0&&qwq) putchar(change(s[i])); else putchar(s[i]); 
    return 0;
}


G. Running in Pairs (CF 1244 G)

题目大意

有两个\(1\)\(n\)的排序\(a,b\)。给定\(k\),要求\(s=\sum\limits_{1\leq i\leq n} \max(a_i,b_i)\leq k\)且最大。

解题思路

我们令\(a\)递增排列,\(s\)最小即为\(\dfrac{n(n+1)}{2}\),最大即为\((\lceil\frac{n}{2}\rceil + 1 + n) \cdot \lfloor\frac{n}{2}\rfloor + n \% 2 \cdot \lceil\frac{n}{2}\rceil\),而对于这之间的数,我们发现都可以取到的。一开始\(b\)先递增排列,然后我们任意交换\(b\)中的两个数,假设位置是\(l,r\)那么答案就会增大\(r-l\),然后再对\((l,r)\)内重复操作即可。最极端的情况就变成\(b\)递减排列,即取得了最大值。故贪心即可。

神奇的代码
#include <bits/stdc++.h>
#define MIN(a,b) ((((a)<(b)?(a):(b))))
#define MAX(a,b) ((((a)>(b)?(a):(b))))
#define ABS(a) ((((a)>0?(a):-(a))))
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<PII> VPII;
typedef vector<LL> VL;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;

template <typename T>
void read(T &x) {
    int s = 0, c = getchar();
    x = 0;
    while (isspace(c)) c = getchar();
    if (c == 45) s = 1, c = getchar();
    while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    if (s) x = -x;
}

template <typename T>
void write(T x, char c = ' ') {
    int b[40], l = 0;
    if (x < 0) putchar(45), x = -x;
    while (x > 0) b[l++] = x % 10, x /= 10;
    if (!l) putchar(48);
    while (l) putchar(b[--l] | 48);
    putchar(c);
}

int main(void) {
    int n;
    LL k;
    read(n);
    read(k);
    k-=(LL)n*(n+1)>>1;
    if (k<0) {puts("-1"); return 0;}
    int p[n+1];
    for(int i=1;i<=n;++i) p[i]=i;
    int l=1,r=n;
    while(k&&l<r){
        while(k<r-l) ++l;
        k-=r-l;
        swap(p[l],p[r]);
        if (k>0) ++l,--r;
    }
    LL ans=0;
    for(int i=1;i<=n;++i) ans+=max(i,p[i]);
    write(ans,'\n');
    for(int i=1;i<=n;++i) printf("%d%c",i,i==n?'\n':' ');
    for(int i=1;i<=n;++i) printf("%d%c",p[i],i==n?'\n':' ');
    return 0;
}


posted @ 2020-02-04 11:52  ~Lanly~  阅读(221)  评论(0编辑  收藏  举报