zoukankan      html  css  js  c++  java
  • Codeforces Round #592 (Div. 2)

    A. Pens and Pencils (CF 1244 A)

    题目大意

    给定(a,b,c,d,k),问是否(lceil dfrac{a}{c} ceil + lceil dfrac{b}{d} ceil 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
    ",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)是楼梯数量,由于(numleq 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,'
    ');
        }
        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)。其中(wgeq d)

    解题思路

    由于(wgeq d),当(ygeq 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
    ",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,'
    ');
            for(int i=1;i<=n;++i) printf("%d%c",best_color[i]+1,i==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,'
    ');
        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=sumlimits_{1leq ileq n} max(a_i,b_i)leq k)且最大。

    解题思路

    我们令(a)递增排列,(s)最小即为(dfrac{n(n+1)}{2}),最大即为((lceilfrac{n}{2} ceil + 1 + n) cdot lfloorfrac{n}{2} floor + n \% 2 cdot lceilfrac{n}{2} ceil),而对于这之间的数,我们发现都可以取到的。一开始(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,'
    ');
        for(int i=1;i<=n;++i) printf("%d%c",i,i==n?'
    ':' ');
        for(int i=1;i<=n;++i) printf("%d%c",p[i],i==n?'
    ':' ');
        return 0;
    }
    


  • 相关阅读:
    Mac上的常用软件
    Mac上在iterm2中使用ls时,出现Operation not permitted
    Typora常用操作
    Mac上的qemusystemaarch64占用太多内存
    软件质量管理总结
    postgres使用记录
    Linux 包含中文字符的文件名无法使用shell 选中或复制
    常见硬件知识
    iterm2 常用操作
    C# 通过 HTTPModule 防范 DOS
  • 原文地址:https://www.cnblogs.com/Lanly/p/12258839.html
Copyright © 2011-2022 走看看