Grakn Forces 2020A - D

    科技2022-07-10  129

    1408A - Circle Coloring

    题意

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

    思路

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

    代码

    #include<iostream> #include<cstring> #include<vector> 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]; vector<int >ans; ans.push_back(last); for(int i = 1;i<n - 1;i++){ if(a[i] != last) last = a[i]; else if(b[i] != last) last = b[i]; else if(c[i] != last) last = c[i]; ans.push_back(last); } if(a[n - 1] != last && a[n - 1] != ans[0]) last = a[n - 1]; else if(b[n - 1] != last && b[n - 1] != ans[0]) last = b[n - 1]; else last = c[n - 1]; ans.push_back(last); for(auto x : ans){ cout<<x<<' '; } puts(""); } return 0; }

    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<iostream> 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) <<endl; } return 0; }

    1408C - Discrete Acceleration

    题意

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

    思路

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

    代码

    #include<iostream> 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<<t1<<' '<<t2<<endl; // 判断谁先走到下一个点,给答案加上这个点对应的时间 // 走到这个点的速度+1,另一个人走这段时间相应的路程 if(t1 < t2){ ans += t1; s = a[i]; e = e - v2 * t1; v1++; i++; } else{ ans += t2; e = a[j]; s = v1 * t2 + s; v2++; j--; } } // cout<<v1<<' '<<v2<<endl; // cout<<e<<' '<<s<<endl; ans += (e - s ) / (v1 + v2); // 剩下的路程一起走的时间 printf("%.8lf\n",ans); } return 0; }

    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<iostream> #include<cstring> using namespace std; const int N = 1e6 + 10,M = 2010; #define x first #define y second typedef pair<int ,int >PII; 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<<ans<<endl; return 0; }
    Processed: 0.041, SQL: 8