Grakn Forces 2020 A - D

1408A - Circle Coloring

题意

给定长度n为三个数组a,b,c其中ai != bi != ci 从中选择一个收尾相连的数组是数组的第i为元素是ai ,bi 或ci 的一个,但相邻的元素不能相同

思路

很简单的一道模拟题,可以从下标为1开始找只要保证这个数和他前面的一个数不相等就可以,最后一个数特判一下,因为ai != bi != ci 所以每个数是必然满足条件的

代码

#include
#include
#include
using namespace std;
const int N = 1e3+10;
int a[N],b[N],c[N];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        for(int i = 0;i < n;i++) scanf("%d",&a[i]);
        for(int i = 0;i < n;i++) scanf("%d",&b[i]);
        for(int i = 0;i < n;i++) scanf("%d",&c[i]);
        int last = a[0];
        vectorans;
        ans.push_back(last);
        for(int i = 1;i

1408B - Arrays Sum

题意

给定一个非严格单调递增的数组a,求数组a可以由最少多少个数组b组成,其中数组b也是非严格单调递增的,但是数组b的元素个数有限,只能为k个

思路

首先先想特殊的
····当所有元素都相同的话只有一个
····当次数为1的话,如果含有不同的元素那么必然不可能
对于剩下的情况
····由于b也是单调递增的,因为最少,我能就尽可能希望每次能够多表示一些ai,不难想到每次除了第一次以外只能表示出k - 1一个a中的元素,所以就等价为 an - an-1 ,…… a3 - a2,a2 - a1 中不为0的所有数即为c,每次选择k - 1个至少需要多少次 ⌈ c k − 1 ⌉ \lceil \frac{c}{k-1} \rceil k1c,(因为第一次可以是k次,所以可以忽略a1使第一次为k - 1次)

代码

#include
 
using namespace std;
const int N = 110;
int a[N];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
        if(a[1] == a[n]) {
            puts("1");
            continue;
        }
        else if(k == 1){
            puts("-1");
            continue;
        }
        int c = 0;
        for(int i = n;i > 1;i--){
            int x = a[i] - a[i - 1];
            if(x > 0) c++;
        }
        cout<<(c + k - 2)/(k - 1) <

1408C - Discrete Acceleration

题意

给定长度为L的一条路,一个人从0出发,一个从L出发,他们相向而行,给定一个数组a(递增)每一次通过a中的一个节点,他的速度就会加1(默认速度为1),求多少秒后,他们会相遇

思路

可以使用双指针的思路,求两个人谁先到达离自己最近的点,然后这个人的速+1,另个一人也走这个时间段的路程,然后继续这个过程,直到所有的点都被用过,最后他们以各自的速度走完剩下的路程

代码

#include
 
using namespace std;
const int N = 1e5+10;
int a[N];
 
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n,l;
        scanf("%d%d",&n,&l);
        for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
        int i = 1,j = n;  // 离他们最近的点
        double s = 0,e = l; //  初始位置
        int v1 = 1,v2 = 1; // 初始速度
        double ans = 0;   // 统计答案
 
        while(i <= j){  // 遍历所有的点
            double t1 = (double)(a[i] - s)/v1;  // 向右走,走到下一个点的 时间
            double t2 = (double)(e - a[j])/v2;  // 向左走,走到下一个点的 时间
            // cout<

1408D - Searchlights

题意

给定n个机器人的坐标(ai,bi)和m个灯光的照射范围(ci,di)(每个灯光可以照射给定点的以下区域),你可以控制所有的机器人,x方向走一个或y方向走一个,询问所有机器人都逃离灯光的照射所需要的最少步数

思路

对于每个机器人走的步数,可以假设为(ai + x, bi + y) ,对于每个照射区域,都要满足 ai + x <= cj ,bi + y <= dj不成立,当 ai + x <= cj ,要满足 y >= dj - bi + 1,所以我们可以用一个数组f表示这种情况,该数组的下标i表示移动的步数小于等于i的情况下需要移动的步数,但是该步数并不是最直接的意思,他还需要依赖大于i的最大步数,比如:
····当 ai <= cj且bi <= dj,我们只需记录f[cj - ai](cj - ai表示最大情况下的x满足ai + x <= cj )需要的步数为 dj - bi + 1,比他小的点默认这个值,所以在统计答案的时候可以从后往前,依次遍历

代码

#include
#include
using namespace std;
const int N = 1e6 + 10,M = 2010;
#define x first
#define y second
typedef pairPII;
PII r[M];
PII s[M];
int f[N];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
        scanf("%d%d",&r[i].x,&r[i].y);
    for(int i = 1;i <= m;i++)
        scanf("%d%d",&s[i].x,&s[i].y);
    for(int i = 1;i <= n;i++)
        for(int j = 1;j <= m;j++){
            if(r[i].x <= s[j].x && r[i].y <= s[j].y)
                f[s[j].x - r[i].x] = max(f[s[j].x - r[i].x],s[j].y - r[i].y + 1);
        }
    int ans = N;
    for(int i = N - 2;i >= 0;i--){
        f[i] = max(f[i],f[i + 1]);
        ans = min(ans,f[i] + i);
        
    }
    cout<

你可能感兴趣的:(codeforces,算法)