zoukankan      html  css  js  c++  java
  • 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;
    }
    


  • 相关阅读:
    Spring Boot 使用 Dom4j XStream 操作 Xml
    Spring Boot 使用 JAX-WS 调用 WebService 服务
    Spring Boot 使用 CXF 调用 WebService 服务
    Spring Boot 开发 WebService 服务
    Spring Boot 中使用 HttpClient 进行 POST GET PUT DELETE
    Spring Boot Ftp Client 客户端示例支持断点续传
    Spring Boot 发送邮件
    Spring Boot 定时任务 Quartz 使用教程
    Spring Boot 缓存应用 Memcached 入门教程
    ThreadLocal,Java中特殊的线程绑定机制
  • 原文地址:https://www.cnblogs.com/Lanly/p/12288422.html
Copyright © 2011-2022 走看看