• Educational Codeforces Round 76 (Rated for Div. 2)


    A. Two Rival Students (CF 1257 A)

    题目大意

    (n)个学生,给定两个学生的初始站位,可以交换最多(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 n,a,x,b;
            read(n);
            read(x);
            read(a);
            read(b);
            if (a>b) swap(a,b);
            int dis=abs(a-1)+abs(n-b);
            if (x>=dis) printf("%d
    ",n-1);
            else printf("%d
    ",b-a+x);
        }
        return 0;
    }
    


    B. Magic Stick (CF 1257 B)

    题目大意

    给定两个数(x,y),问能否通过以下两种操作使得(x=y)

    • (x)是偶数,则(x=dfrac{3x}{2})
    • (x>1),则(x=x-1)

    可以操作无限次。

    解题思路

    我们发现一旦(x>3),则(x)可以越来越大,此时一定可以使得(x=y)。而当(x=2)(x)就在(2,3)徘徊,或者到(1),这个时候再看(y)在哪就好了。

    神奇的代码
    #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 x,y;
            read(x);
            read(y);
            if (x>3) puts("YES");
            else if (x==1&&y!=1) puts("NO");
            else if (y<4) puts("YES");
            else puts("NO");
        }
        return 0;
    }
    


    C. Dominated Subarray (CF 1257 C)

    题目大意

    一个数组中,出现最多的那个数(只能有一个数)能统治这个数组,如果有多个数则没有数能统治。先给定一数组(a),问最短的有数字统治的长度的子数组(在原数组连续)是多少。

    解题思路

    在最短的子数组里,首尾的数字一定是相同的且这个数字出现了两次,因为如果里面有出现两次及以上的数字的话,这个子数组的长度能更短,所以就从左到右扫一遍,遇到每一个数,与这个数上一次出现的位置作差得到一个长度取最小值即可。

    神奇的代码
    #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);
            int a[n+1]={0};
            for(int i=1;i<=n;++i) read(a[i]);
            unordered_map<int,int> qwq;
            int ans=1e9+7;
            for(int i=1;i<=n;++i){
                if (qwq[a[i]]==0) qwq[a[i]]=i;
                else{
                    ans=min(ans,i-qwq[a[i]]+1);
                    qwq[a[i]]=i;
                }
            }
            if (ans==1e9+7) puts("-1");
            else printf("%d
    ",ans);
        }
        return 0;
    }
    


    D. Yet Another Monster Killing Problem (CF 1257 D)

    题目大意

    (n)个怪兽各有一定的攻击力(a_i),现有(m)个英雄对应的攻击力和耐力值分别为(p_i)(s_i)。先派英雄依次打败这(n)个怪兽,如果怪兽的攻击力大于所派英雄攻击力则英雄撤退回来,或者英雄的耐力值为(0)也回来,或者中途撤退回来。英雄每打败一只怪兽其耐力值就减一。问最少派多少次英雄才能打完全部怪兽。一个英雄可以派任意多次。如果不能打完所有怪兽输出(-1)

    解题思路

    注意到可以中途撤退,那么我们维护一个数组(ins[i]=maxlimits_{s_j geq i}(p_j)),表示能打(i)次怪兽的英雄的最大攻击力,然后每次贪心看最多能打多少个怪兽即可。

    神奇的代码
    #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);
            int dps[n+1];
            memset(dps,0,sizeof(dps));
            int max_dps=0;
            for(int i=1;i<=n;++i) read(dps[i]),max_dps=max(dps[i],max_dps);
            int m;
            read(m);
            int ins[n+1];
            memset(ins,0,sizeof(ins));
            int max_ins=0;
            for(int u,v,i=1;i<=m;++i){
                read(u);
                read(v);
                max_ins=max(max_ins,u);
                ins[v]=max(u,ins[v]);
            }
            if (max_ins<max_dps) {puts("-1"); continue;}
            for(int i=n-1;i>=1;--i) ins[i]=max(ins[i],ins[i+1]);
            int ans=0;
            int id=1;
            while(id<=n){
                int qwq=dps[id];
                int cnt=1;
                while(qwq<=ins[cnt]&&id<=n){
                    ++id;
                    qwq=max(qwq,dps[id]);
                    cnt++;
                }
                ++ans;
            }
            write(ans,'
    ');
        }
        return 0;
    }
    


    E. The Contest (CF 1257 E)

    题目大意

    三组数,第(i)组有(k_i)个数,分别是(k_{ij})。所有数各不相同且(1leq k_{ij} leq n)。现在要求第一组里的数是(1)~(q),第二组里的数是(q+1)~(p),第三组里的数是(p+1)~(n)(q,p)任意,甚至可以有一组或者两组里没有数。现在可以进行一种操作,即从一组数中取一个数放到另一组。问最小操作的次数。

    解题思路

    我们设(pos[i])表示数字(i)在第几组,然后我们枚举第一组的个数,考虑最小的操作次数。
    当第一组的个数为(l),那么数字(1)~(l)都必须在第一组里,那么第一组要满足要求所产生的操作数就是(pos[1..l])中非(1)的个数以及(pos[l+1..n])(1)的个数,对于第三组,我们假设有(p)~(n)都在里面,那么第三组产生的贡献就是(pos[p..n])(2)的个数以及(pos[l+1..p-1])(3)的个数。那么我们设(ncnt1[i])表示(pos[1..i])(1)的个数,(cnt1[i])表示(pos[i..n])(1)的个数,(cnt2[i])表示(pos[i..n])(2)的个数,(cnt3[i])表示(pos[1..i])(3)的个数。那么(dp[l]=minlimits_{p>l}(ncnt1[l]+cnt1[l+1]+cnt2[p]+cnt3[p-1]-cnt3[l]))。关于(p)(l)无关,储存最小值即可(O(1))转移。时间复杂度(O(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 k1,k2,k3;
        read(k1);
        read(k2);
        read(k3);
        int n=k1+k2+k3;
        int pos[n+1];
        memset(pos,0,sizeof(pos));
        for(int u,i=1;i<=k1;++i){
            read(u);
            pos[u]=1;
        }
        for(int u,i=1;i<=k2;++i){
            read(u);
            pos[u]=2;
        }
        for(int u,i=1;i<=k3;++i){
            read(u);
            pos[u]=3;
        }
        int cnt1[n+2],ncnt1[n+2],cnt2[n+2],cnt3[n+2];
        memset(cnt1,0,sizeof(cnt1));
        memset(ncnt1,0,sizeof(ncnt1));
        memset(cnt2,0,sizeof(cnt2));
        memset(cnt3,0,sizeof(cnt3));
        for(int i=1;i<=n;++i){
            ncnt1[i]=ncnt1[i-1]+(pos[i]!=1);
            cnt3[i]=cnt3[i-1]+(pos[i]==3);
        }
        for(int i=n;i>=1;--i){
            cnt1[i]=cnt1[i+1]+(pos[i]==1);
            cnt2[i]=cnt2[i+1]+(pos[i]==2);
        }
        int ans=1e9+7;
        int qwq=cnt2[n+1]+cnt3[n];
        for(int i=n;i>=0;--i){
            ans=min(ans,ncnt1[i]+cnt1[i+1]+qwq-cnt3[i]);
            if (i!=0) qwq=min(qwq,cnt2[i]+cnt3[i-1]);
        }
        write(ans,'
    ');
        return 0;
    }
    


    F. Make Them Similar (CF 1257 F)

    题目大意

    (n)个数,要求选一个数(x)与它们异或,使得异或后的数在二进制下都有相同个数的(1)。如果不存在这样的(x)输出(-1)

    解题思路

    由于(xleq 2_{30}-1),在二进制下,各位互不干扰,我们可以枚举前(15)位的情况分别与这(n)个数异或,得到(1)的个数,第(i)个数设为(l_i),然后再枚举后(15)位的情况分别异或,得到(1)的个数,第(i)个数设为(r_i),看看是否存在一个方案使得两个(15)位对(1)的个数的和相等,即满足(forall i,j in [1,n],l_i+r_i=l_j+r_j),移项得(l_j-l_i=r_i-r_j)。对于(l_i)我们设(cl_i=l_i-l_1),把(cl_i)数组(Hash)或者用(map)或者丢到(set)里,对于(r_i)我们设(cr_i=r_1-r_i),当得到一组(cr_i)时去找有没有和它相等的(cl_i)即可。时间复杂度(O(n2^{20}))

    神奇的代码
    #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);
    }
    
    const int N=106;
    
    int n,ans;
    
    int a[N],cnt[N];
    
    int tmp;
    
    struct data{
        array<int,102> aa;
        int ans;
        bool operator<(const data &a)const{
            return aa<a.aa;
        }
    };
    
    set<data> qwq;
    
    int cout1(int x){
        if (x==0) return 0;
        else return cout1(x>>1)+(x&1);
    }
    
    void DFS1(int x){
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;++i) cnt[i]=cout1((a[i]&tmp)^x);
        data qaq;
        qaq.aa.fill(0);
        for(int i=0;i<n-1;++i) qaq.aa[i]=cnt[i+2]-cnt[1];
        qaq.ans=x;
        qwq.insert(qaq);
    }
    
    void DFS2(int x){
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;++i) cnt[i]=cout1((a[i]>>15<<15)^x);
        data qaq;
        qaq.aa.fill(0);
        for(int i=0;i<n-1;++i) qaq.aa[i]=cnt[1]-cnt[i+2];
        qaq.ans=0;
        auto it=qwq.find(qaq);
        if (it!=qwq.end()) ans=x^((*it).ans);
    }
    
    int main(void) {
        for(int i=0;i<15;++i) tmp|=(1<<i);
        read(n);
        ans=-1;
        for(int i=1;i<=n;++i) read(a[i]);
        int len=(1<<15);
        for(int i=0;i<len;++i){
            if (ans!=-1) break;
            DFS1(i);
        }
        for(int i=1;i<len;++i){
            if (ans!=-1) break;
            DFS2((i<<15));
        }
        if (ans==-1) puts("-1");
        else printf("%d
    ",ans);
        return 0;
    }
    


  • 相关阅读:
    2020/12/2
    2020/12/1
    Cannot do a soft reset in the middle of a merge
    webpack img
    rm -fr ".git/rebase-apply"
    css 颜色
    初始化样式
    a标签
    esma 最新
    前端
  • 原文地址:https://www.cnblogs.com/Lanly/p/12288422.html
Copyright © 2020-2023  润新知