Grakn Forces 2020部分题解

Problem A

要求从三个数组中每个位置取一个数字,构成一个相同长度的数组,要求相邻的不相等(环形),那么我们直接暴力选,记录当前不能取的值就可以了,然后要记得特判一下首位的两个元素。

Problem B

首先通过模拟样例我们发现相同的元素其实是一点用都没有的,所以我们先去重了再说,然后我们的做法就是贪心的取四个不同的元素一直到取完为止。

#include<cstdio>
#include<algorithm>
#include<functional>
#include<vector>
#include<numeric>
#include<queue>
#include<map>
#include<set>
#include<unordered_map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005 
#define fi first 
#define se second
#define pb push_back
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
void check_max (int &a,int b) { a=max (a,b);}
void check_min (int &a,int b) { a=min (a,b);}
const int maxn=3e5+10;
int t;

void solve () {
    int n,k;
    scanf ("%d%d",&n,&k);
    vector <int> v (n);
    for (auto &it:v) scanf ("%d",&it);
    v.erase (unique (v.begin (),v.end ()),v.end ());
    int len=v.size ();
    if (k==1&&v.size ()>=2) {
        printf ("-1
");
        return ;
    }
    else if (len<=k) {
        printf ("1
");
        return ;
    }
    int ans;
    if ((len-k)%(k-1)==0) ans=(len-k)/(k-1)+1;
    else ans=(len-k)/(k-1)+2; 
    printf ("%d
",ans);
}

int main () {
    scanf ("%d",&t);
    while (t--) {
        solve ();
    }
    return 0;
}

Problem C

考虑二分时间,然后check函数模拟行程并判断。代码在第四个样例的时候会T掉出不来,不知道为什么,大概思路就是这个,大佬可以找找看bug。

#include<cstdio>
#include<algorithm>
#include<functional>
#include<vector>
#include<numeric>
#include<queue>
#include<map>
#include<set>
#include<unordered_map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-10
#define N 1000005 
#define fi first 
#define se second
#define pb push_back
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
void check_max (int &a,int b) { a=max (a,b);}
void check_min (int &a,int b) { a=min (a,b);}
int t,n,m;

inline bool check (double time,vector<int> &now) {
    double  total=0;
    double x=0,v=1;
    double res=time;
    rev (i,0,n) {
        double cost=(now[i]-x)/v;
        if (res>=cost)  {
            res-=cost;
            x=now[i];
            v++;
        }
        break;
    }
    x+=res*v;
    total+=x;
    x=m,res=time,v=1;
    for (int i=n-1;i>=0;i--) {
        double cost=(x-now[i])/v;
        if (cost<=res) {
            res-=cost;
            v++;
            x=now[i];
        }
        break;
    }
    x-=res*v;
    total+=m-x;
    return total>=m;
}

void solve (){
    scanf ("%d%d",&n,&m);
    vector <int>   a(n);
    for (auto &it:a) scanf ("%d",&it);
    double l=0.0,r=m;
    double ans;
    while (r-l>exp) {
        double mid= (l+r)*0.5;
        if (check (mid,a)) r=mid-exp,ans=mid;
        else l=mid+exp;
    }
    printf ("%.10lf
",ans);
}

int main () {
    scanf ("%d",&t);
    while (t--) {
        solve ();
    }
    return 0;
}

Problem D

本来的想法是找横纵坐标的最小值,但是显然是错的。所以我们可以考虑一下dp,这题我们很明显如果要所以的小偷都不看见,那么一定是一部分在右边,一部分在上面,所以我们肯定是在这些状态里面取一个最小值作为答案,我们很容易就可以把对应移动多少横坐标最少需要的纵坐标给算出来,然后枚举一下横坐标移动的值,维护一个dp的最大前缀和对答案取min就好了。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005 
#define fi first 
#define se second
#define pb push_back
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
void check_max (int &a,int b) { a=max (a,b);}
void check_min (int &a,int b) { a=min (a,b);}
inline int read() {
    char ch=getchar(); int x=0, f=1;
    while(ch<'0'||ch>'9') {
        if(ch=='-') f=-1;
        ch=getchar();
    } while('0'<=ch&&ch<='9') {
        x=x*10+ch-'0';
        ch=getchar();
    } return x*f;
}
const int maxn=1e6+10;

int main () {
    int n,m;
    scanf ("%d%d",&n,&m);
    vector <int> a(n),b(n);
    vector <int> c(m),d(m);
    rev (i,0,n) scanf ("%d%d",&a[i],&b[i]);
    rev (i,0,m) scanf ("%d%d",&c[i],&d[i]);
    vector <int> dp(maxn);
    rev (i,0,n) 
     rev (j,0,m) {
        if (c[j]>=a[i]) {
            check_max (dp[c[j]-a[i]],d[j]-b[i]+1);
        }
    }
    int ans=2*maxn;
    int mx=0;
    per (i,maxn-1,0) {
        check_max (mx,dp[i]);
        check_min (ans,mx+i);
    }
    printf ("%d
",ans);
}
原文地址:https://www.cnblogs.com/hhlya/p/13762734.html