zoukankan      html  css  js  c++  java
  • 牛客练习赛3

    题目链接: https://www.nowcoder.com/acm/contest/13#question

    A.反蝴蝶效应

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int maxn=100005;
    int n;
    int a[maxn];
    int main(){
        cin>>n;
        int ans=0;
     for(int i=1;i<=n;i++){
         scanf("%d",&a[i]);
           ans=max(a[i]+i-1,ans);
     
         }
        cout<<ans<<endl;
    }

    B.贝伦卡斯泰露

    dfs暴力搜索,加几个优化

    1. 首先判断相同的数是否出现偶数次

    2. 记录每个数的总出现次数,若在某一个集合出现偶数次则跳出

    3. 若对于两个集合已经选择的数已经不是对应相等则跳出

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    vector<int> g1;
    vector<int> g2;
    int read(){
        char ch;
        int x=0,f=1;ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int a[45],num[45],num1[45],num2[45];
    int n;
    bool dfs(int x){
        int z=min(g1.size(),g2.size());
        if(x==n+1){
            if(z!=n/2)
                return false;
            for(int i=0;i<n/2;i++){
                if(g1[i]!=g2[i])
                    return false;
            }
            return true;
        }
        if(g1.size()>n/2||g2.size()>n/2)
            return false;
     
        for(int i=0;i<z;i++){
            if(g1[i]!=g2[i])
                return false;
        }
        int p=a[x];
        if(num1[p]<num[p]/2){
            num1[p]++;
            g1.push_back(p);
            if(dfs(x+1))
                return true;
            num1[p]--;
            g1.pop_back();
        }
        if(num2[p]<num[p]/2){
            num2[p]++;
            g2.push_back(p);
            if(dfs(x+1))
                return true;
            num2[p]--;
            g2.pop_back();
        }
        return false;
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            memset(num,0,sizeof(num));
            memset(num1,0,sizeof(num2));
            memset(num2,0,sizeof(num2));
            g1.clear();
            g2.clear();
            scanf("%d",&n);
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                num[a[i]]++;
            }
            bool f=1;
            for(int i=1;i<=40;i++)
                if(num[a[i]]%2!=0){
                    printf("Furude Rika\n");
                    f=0;
                    break;
                }
            if(!f)
                continue;
            if(dfs(1))
                printf("Frederica Bernkastel\n");
            else printf("Furude Rika\n");
     
        }
    }

    C 不会。。。

    D.生物课程

    首先只能有n-1条边,其次判断每个点所连接的点数,注意点较少时的特判

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int maxn=100005;
    int n,m;
    int num[maxn];
    int main(){
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            int x,y;
            cin>>x>>y;
            if(x!=y){
                num[x]++;
                num[y]++;
            }
        }
        if(m!=n-1){
            cout<<"NotValid"<<endl;
            return 0;
        }
        if(n==2){
            if(m==1&&num[1]==num[2]&&num[1]==1)
            cout<<"I"<<endl;
            return 0;
        }
     
     
            sort(num+1,num+1+n);
            if(num[1]==num[2]&&num[1]==1&&num[3]==num[n]&&num[3]==2){
                cout<<"I"<<endl;
                return 0;
            }
     
            if(n>=5&&num[n]==4&&num[n-1]<num[n]&&num[1]==num[4]&&num[1]==1&&num[4]<num[5]){
                cout<<"X"<<endl;
                return 0;
            }
            if(n>=4&&num[n]==3&&num[n-1]<num[n]&&num[1]==num[3]&&num[1]==1&&num[3]<num[4]){
                cout<<"Y"<<endl;
                return 0;
            }
    cout<<"NotValid"<<endl;
    }

    E.绝对半径2051

    首先将相同的数的下标记录到同一个vector里,再二分答案,对于每个容器里的数判断是否满足

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    using namespace std;
    const int maxn=100005;
      int z=0;
    struct P{
    int x,i;
    }p[maxn];
    int vis[maxn];
    int n,k;
    vector<int> g[maxn];
    int a[maxn];
     
     
    int read(){
        char ch;
        int x=0,f=1;ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
     
    bool cmp(P a,P b){
        if(a.x!=b.x)
            return a.x<b.x;
        return a.i<b.i;
    }
     
    bool C(int x){
        for(int i=1;i<=z;i++)
            for(int j=0;j<g[i].size();j++){
                if(g[i].size()-j<x)
                    continue;
                int c=j+x-1;
                if(g[i][c]-g[i][j]+1>k+x)
                    continue;
                return true;
            }
        return false;
    }
    int main(){
     
        n=read();
        k=read();
        for(int i=1;i<=n;i++){
            p[i].x=read();
            a[i]=p[i].x;
            p[i].i=i;
        }
        if(n==0){
            printf("0\n");
            return 0;
        }
        sort(p+1,p+1+n,cmp);
     
        for(int i=1;i<=n;i++){
            if(p[i].x!=p[i-1].x){
                z++;
                //vis[p[i].i]=z;
            }
            vis[p[i].i]=z;
            g[z].push_back(p[i].i);
           // cout<<z<<p[i].i<<vis[p[i].i]<<-1<<endl;
        }
        int l=1,r=1e9+1;
        for(int i=1;i<=60;i++){
            int mid=(l+r)/2;
            if(C(mid))
                l=mid;
            else r=mid;
        }
        if(C(r))
            printf("%d\n",r);
        else printf("%d\n",l);
    }

    F.监视任务

    先将所有的区间按照右端点进行排序,根据贪心的思想,每次用树状数组求(l[i],r[i])区间的和,若大于等于k[i],则不需操作,否则从r[i]开始向左进行操作,将不是1的全部改为1,直至区间和为k[i]

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    const int maxm=1000005;
    const int maxn=500005;
    int bit[maxn],vis[maxn];
    int n,m;
    struct P{
     int l,r,z;
    }p[maxm];
    int sum(int x){
        int s=0;
        while(x>0){
            s+=bit[x];
            x-=(x&-x);
        }
        return s;
    }
    void add(int x){
        while(x<=n){
            bit[x]+=1;
            x+=(x&-x);
        }
    }
    int read(){
        char ch;
        int x=0,f=1;ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    bool cmp(P a,P b){
        if(a.r!=b.r)
            return a.r<b.r;
        return a.l<b.l;
    }
    int main(){
        n=read();
        m=read();
        for(int i=1;i<=m;i++){
            p[i].l=read();
            p[i].r=read();
            p[i].z=read();
        }
        sort(p+1,p+m+1,cmp);
        for(int i=1;i<=m;i++){
            int z=sum(p[i].r)-sum(p[i].l-1);
     
            if(z>=p[i].z)
                continue;   // cout<<z<<" "<<p[i].z<<-1<<endl;
            int k=p[i].z-z;
            for(int j=p[i].r;j>=p[i].l&&k>0;j--){
                if(!vis[j]){
                    vis[j]=1;
                    k--;
                    add(j);
                }
            }
        }
        printf("%d\n",sum(n));
    }
    

      

  • 相关阅读:
    牛客网·剑指offer 从尾到头打印链表(JAVA)
    牛客网·剑指offer 替换空格(JAVA)
    简单的用户登录后台程序编写
    牛客网&剑指offer 二维数组中的查找(JAVA)
    洛谷 P1603 斯诺登的密码(JAVA)
    【回溯法】八皇后问题(递归和非递归)
    如何使用SecureCRT让Vim有颜色?
    js 转base64字符串为文件
    springboot 测试类
    oracle 登录、重启服务
  • 原文地址:https://www.cnblogs.com/dlutjwh/p/10986848.html
Copyright © 2011-2022 走看看