Codeforces Round #808 (Div. 2)
C - Doremy's IQ
-
这题如果是正面强行搜索可以说是一定会超时,所以这边需要换个角度
-
我们这边可以从反向思考,正面如果遇到难题会降智,那么反向遇到难题是不是能看成升智呢,所以我们这边采用从后往前遍历
-
智商从零开始,遇到难题则升智商,直到升到高智商为止,这时候遇到再难的题目就不能做了,跳过
#include <bits/stdc++.h> using namespace std; void solve(){ int n, q; cin >> n >> q; int Q = 0; int a[n+1]; string s = "";//用字符串累加,方便加数字及输出 for(int i = 1; i <= n; i ++) cin >> a[i]; for(int i = n; i > 0; i --){ if (q != Q){ //智商为满时,每次开始都参加 s = "1" + s; if (Q < a[i]) Q ++;//遇到难题,升智 } else { //智商升满了,在遇到难题就不能做了 if (Q >= a[i]) s = "1" + s; else s = "0" + s; } } cout << s << '\n'; return; } int main(){ int n; cin >> n; while(n --) solve(); return 0; }
D - Difference Array
-
本题让我们求n-1次差分数组,由于n的数字极大,毫无疑问会超时,因此可以剪枝
-
通过观察可以发现,其中最奇怪的数字便是0,如果有一串零,一轮差分后仅仅是数量减一,而且相同的数字差分也会变成零
-
所以在全体的遍历中,我们对于零做的功又多又没意义
-
所以我们这边做个规定,从后往前差分,直到遇见第一个零做完差分(零个数减一符合零的性质)或者结束整个数组为止
-
这样子规定之后对于零差分的工程减少,而且新一轮的排序可以从最后一个零开始,同时也减少了这方面的开销
#include <bits/stdc++.h> using namespace std; const int MAX = 2e5+10; int a[MAX]; void solve(){ int n; cin >> n; for(int i = 0; i < n; i ++) cin >> a[i]; int i; for(i = n-2; i >= 0; i --){ int pre = a[i+1];//存储对于下一轮来说a(i-1)的数值 int j; for(j = i; j >= 0; j --){ a[j] = pre-a[j];//差分 pre -= a[j];//通过差值回溯出未差分的a[j] if (!pre) break;//遇见第一个完成差分的零,结束差分 } sort(a+j, a+i+1);//从差分结束位置开始排序 if (i == 0 || !a[i-1]) break;//除零外只有一个数字,直接结束 } cout << a[i] << '\n'; return; } int main (){ int n; cin >> n; while(n --) solve(); return 0; }