Grakn Forces 2020(ABCD)

A. Circle Coloring

签到,abc三个数组找到一个符合要求的就行了

#include <bits/stdc++.h>
using namespace std;
int a[105],b[105],c[105];
int main(){
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)cin>>b[i];
        for(int i=1;i<=n;i++)cin>>c[i];
        int last=a[1];
        cout<<last<<' ';
        for(int i=2;i<=n-1;i++){
            if(a[i]!=last)cout<<a[i]<<' ',last=a[i];
            else if(b[i]!=last)cout<<b[i]<<' ',last=b[i];
            else if(c[i]!=last)cout<<c[i]<<' ',last=c[i];
        }
        if(a[n]!=a[1]&&a[n]!=last)cout<<a[n];
        else if(b[n]!=a[1]&&b[n]!=last)cout<<b[n];
        else if(c[n]!=a[1]&&c[n]!=last)cout<<c[n];
        cout<<endl;
    }
}

B. Arrays Sum

想了挺久的B
发现一个b能够消掉不同的k-1个数字(另一个为0)
不过要记得特判一下 c n t = 1 cnt=1 cnt=1的情况以及保证 a n s > = 1 ans>=1 ans>=1

#include <bits/stdc++.h>
using namespace std;
int a[105];
int main(){
    int t;cin>>t;
    while(t--){
        int n,k;cin>>n>>k;
        set<int>q;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            q.insert(a[i]);
        }
        int cnt=q.size();//统计有几个不同的数字
        if(k==1){
            if(cnt==1)cout<<1<<endl;
            else cout<<-1<<endl;
            continue;
        }
        int ans;
        if((cnt-1)%(k-1)==0)ans=(cnt-1)/(k-1);
        else ans=(cnt-1)/(k-1)+1;
        cout<<max(1,ans)<<endl;//这里大概是赛后fst的点?
    }
}

C. Discrete Acceleration

就模拟,也发现有二分时间的做法
由于比赛时变量定义太混乱,就不上代码了

D. Searchlights

看错了n和m的数据范围,还以为是1e6的,在想怎么用O( n l o g n nlogn nlogn)做,实际上最大只有2000
根据题意,强盗必须在x和y至少一个方面大于探照灯which means 如果 x < = c j − a i x<=c_j-a_i x<=cjai,那么 y > = d j − b i + 1 y>=d_j-b_i+1 y>=djbi+1
因为上界不大,因此我们用f数组的下标存每个x的位置,让其等于y的最小值,即 f ( c j − a i ) = m a x ( f ( c j − a i ) , d j − b i + 1 ) f_(c_j-a_i)=max(f_(c_j-a_i) , d_j-b_i+1) f(cjai)=max(f(cjai),djbi+1),所以用O( n m nm nm)处理
最后f数组记录后缀的最大值,然后加上向右需要移动的距离求个最小值
为什么是求后缀的最大值呢,比如对于 1 < x < C 1<x<C 1<x<C,1到x-1的这段只需要向右移动x就行,x到C的这段需要向上移动,向上移动的距离就是x到C每个点需要移动的最大值,所以是记录后缀的最大值
时间复杂度 O ( n m + C ) O(nm+C) O(nm+C)

#include <bits/stdc++.h>
using namespace std;
int a[2005],b[2005],c[2005],d[2005],f[2000005];
int main(){
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i]>>b[i];
    for(int i=1;i<=m;i++)cin>>c[i]>>d[i];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i]<=c[j]){
                f[c[j]-a[i]]=max(f[c[j]-a[i]],d[j]-b[i]+1);
            }
        }
    }
    int ans=2000000+2;
    int maxs=0;
    for(int i=1000001;i>=0;i--){
        maxs=max(maxs,f[i]);
        ans=min(ans,i+maxs);
    }
    cout<<ans<<endl;
}

再给一个二分的做法

#include <bits/stdc++.h>
using namespace std;
int a[2005],b[2005],c[2005],d[2005],f[2000005];
int n,m;
bool check(int mid){
    for(int i=0;i<=mid;i++)f[i]=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int sum=c[j]+d[j]-a[i]-b[i]-mid;
            if(a[i]<=c[j]&&b[i]<=d[j]&&sum>=0){
                f[max(0,c[j]-a[i]-sum)]++;
                f[c[j]-a[i]+1]--;
            }
        }
    }
    for(int i=1;i<=mid;i++)f[i]+=f[i-1];
    for(int i=0;i<=mid;i++)if(f[i]==0)return 1;
    return 0;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>a[i]>>b[i];
    for(int i=1;i<=m;i++)cin>>c[i]>>d[i];
    int l=0,r=2e6,ans=0;
    while(l<=r){
        int mid=(l+r)/2;
        if(check(mid))ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans<<endl;
}

剩余待补题完写

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值