牛客练习赛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));
}

  

 

上一篇:LCS


下一篇:E1. Distance Tree (easy version) 题解(思维)