Codeforces Round #769 (Div. 2) ABCD
A. ABC
签到,不解释
#include <iostream>
#include <vector>
using namespace std;
int main() {
int t;
cin >> t;
while(t--) {
string s;
int n;
cin >> n;
cin >> s;
if(s.size() <= 2) {
if(s.size() == 1 || s[0] != s[1]) puts("YES");
else puts("NO");
}
else puts("NO");
}
return 0;
}
B. Roof Construction
It has finally been decided to build a roof over the football field in School 179. Its construction will require placing 𝑛n consecutive vertical pillars. Furthermore, the headmaster wants the heights of all the pillars to form a permutation 𝑝p of integers from 00 to 𝑛−1n−1, where 𝑝𝑖pi is the height of the 𝑖i-th pillar from the left (1≤𝑖≤𝑛)(1≤i≤n).
As the chief, you know that the cost of construction of consecutive pillars is equal to the maximum value of the bitwise XOR of heights of all pairs of adjacent pillars. In other words, the cost of construction is equal to max1≤𝑖≤𝑛−1𝑝𝑖⊕𝑝𝑖+1max1≤i≤n−1pi⊕pi+1, where ⊕⊕ denotes the bitwise XOR operation.
Find any sequence of pillar heights 𝑝p of length 𝑛n with the smallest construction cost.
In this problem, a permutation is an array consisting of 𝑛n distinct integers from 00 to 𝑛−1n−1 in arbitrary order. For example, [2,3,1,0,4][2,3,1,0,4] is a permutation, but [1,0,1][1,0,1] is not a permutation (11 appears twice in the array) and [1,0,3][1,0,3] is also not a permutation (𝑛=3n=3, but 33 is in the array).
Input
Each test contains multiple test cases. The first line contains the number of test cases 𝑡t (1≤𝑡≤1041≤t≤104). Description of the test cases follows.
The only line for each test case contains a single integer 𝑛n (2≤𝑛≤2⋅1052≤n≤2⋅105) — the number of pillars for the construction of the roof.
It is guaranteed that the sum of 𝑛n over all test cases does not exceed 2⋅1052⋅105.
Output
For each test case print 𝑛n integers 𝑝1p1, 𝑝2p2, ……, 𝑝𝑛pn — the sequence of pillar heights with the smallest construction cost.
If there are multiple answers, print any of them.
Example
input
Copy
4
2
3
5
10
output
Copy
0 1
2 0 1
3 2 1 0 4
4 6 3 2 0 8 9 1 7 5
巧妙的思维题,首先按照题目的意思找到一个排列使得排列中相邻两数异或的最大值最小,那么自然想到分析1出现到的最高位,这时候会发现,不论在这一位为1的数有多少个/怎么排列,至少有一个数会接触到这一位为0的数,因此最终答案的这一位必然是1。既然这样,就把这一部分数排到最后面,然后让这一部分最靠左的数与把这个数最高位1取反的数相邻,就是满足题目要求的排列了。
距离来说,比如序列为[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],那么8、9,10这个三个数的第三位都为1,就把它们放在最后面,此时如果8在这三个数的最左边,就让它与0相邻;如果是9就让其与1相邻,如果是10就让其与2相邻;这样得到的最大异或值一定是8(如果任意排列,最终这个异或值不可能比8小)。
#include <iostream>
#include <vector>
using namespace std;
int n, a[200005];
int count(int x) {
int ans = 0;
while(x) {
ans += (x & 1);
x >>= 1;
}
return ans;
}
vector<int> cnt[32];
int main() {
int t;
cin >> t;
while(t--) {
cin >> n;
memset(cnt, 0, sizeof(cnt));
int hi = 0;
for(int i = 0; i <= n - 1; i++) {
for(int j = 0; j < 32; j++) {
if((i >> j) & 1) {
cnt[j].push_back(i);
hi = max(hi, j);
}
}
}
for(int i = 0; i < n; i++) {
a[i] = i;
}
swap(a[(1 << hi) ^ cnt[hi][0]], a[cnt[hi][0] - 1]);
for(int i = 0; i < n; i++) {
cout << a[i] << " ";
}
cout << endl;
}
return 0;
}
C. Strange Test
Igor is in 11th grade. Tomorrow he will have to write an informatics test by the strictest teacher in the school, Pavel Denisovich.
Igor knows how the test will be conducted: first of all, the teacher will give each student two positive integers 𝑎a and 𝑏b (𝑎<𝑏a<b). After that, the student can apply any of the following operations any number of times:
- 𝑎:=𝑎+1a:=a+1 (increase 𝑎a by 11),
- 𝑏:=𝑏+1b:=b+1 (increase 𝑏b by 11),
- 𝑎:=𝑎 | 𝑏a:=a | b (replace 𝑎a with the bitwise OR of 𝑎a and 𝑏b).
To get full marks on the test, the student has to tell the teacher the minimum required number of operations to make 𝑎a and 𝑏b equal.
Igor already knows which numbers the teacher will give him. Help him figure out what is the minimum number of operations needed to make 𝑎a equal to 𝑏b.
Input
Each test contains multiple test cases. The first line contains the number of test cases 𝑡t (1≤𝑡≤1041≤t≤104). Description of the test cases follows.
The only line for each test case contains two integers 𝑎a and 𝑏b (1≤𝑎<𝑏≤1061≤a<b≤106).
It is guaranteed that the sum of 𝑏b over all test cases does not exceed 106106.
Output
For each test case print one integer — the minimum required number of operations to make 𝑎a and 𝑏b equal.
Example
input
Copy
5
1 3
5 8
2 5
3 19
56678 164422
output
Copy
1
3
2
1
23329
乍一看是数学,其实是暴力。首先注意到如果用了一次|以后a一定大于等于b,此时b只能通过不断+1追上来,因此OR最多只用一次。然后分两种情况:a先+、再进行OR、b再+以及b先+、再进行OR、b再+;分别计算答案取最小即可。 注意第二种情况加法次数上界的问题,因为b范围1e6,所以最多进行b次加法(此时相当于b进行了左移,之后再操作一定不如先OR再b++更优),这个上界取得比较宽~
#include <iostream>
#include <vector>
#define ll long long
using namespace std;
int a, b;
int gethi(int x) {
int mx = 0;
for(int i = 0; i < 32; i++) {
if((x >> i) & 1) {
mx = max(mx, i);
}
}
return mx;
}
signed main() {
int t;
cin >> t;
while(t--) {
cin >> a >> b;
int ans = 0x3f3f3f3f;
ans = min(ans, b - a);
for(int i = 0; a + i <= b; i++) {//a先+ 再 or b再+
int tans = 1 + i, ta = (a + i) | b;
tans += ta - b;
ans = min(ans, tans);
}
for(int i = 0; i <= b; i++) {
int tans = 1 + i, tb = (b + i);//b先+ 再or b再+
int ta = a | tb;
tans += ta - tb;
ans = min(ans, tans);
}
cout << ans << endl;
}
return 0;
}
//用了一次|之后b只能通过加法追上来
D. New Year Concert
New Year is just around the corner, which means that in School 179, preparations for the concert are in full swing.
There are 𝑛n classes in the school, numbered from 11 to 𝑛n, the 𝑖i-th class has prepared a scene of length 𝑎𝑖ai minutes.
As the main one responsible for holding the concert, Idnar knows that if a concert has 𝑘k scenes of lengths 𝑏1b1, 𝑏2b2, ……, 𝑏𝑘bk minutes, then the audience will get bored if there exist two integers 𝑙l and 𝑟r such that 1≤𝑙≤𝑟≤𝑘1≤l≤r≤k and gcd(𝑏𝑙,𝑏𝑙+1,…,𝑏𝑟−1,𝑏𝑟)=𝑟−𝑙+1gcd(bl,bl+1,…,br−1,br)=r−l+1, where gcd(𝑏𝑙,𝑏𝑙+1,…,𝑏𝑟−1,𝑏𝑟)gcd(bl,bl+1,…,br−1,br) is equal to the greatest common divisor (GCD) of the numbers 𝑏𝑙bl, 𝑏𝑙+1bl+1, ……, 𝑏𝑟−1br−1, 𝑏𝑟br.
To avoid boring the audience, Idnar can ask any number of times (possibly zero) for the 𝑡t-th class (1≤𝑡≤𝑘1≤t≤k) to make a new scene 𝑑dminutes in length, where 𝑑d can be any positive integer. Thus, after this operation, 𝑏𝑡bt is equal to 𝑑d. Note that 𝑡t and 𝑑d can be different for each operation.
For a sequence of scene lengths 𝑏1b1, 𝑏2b2, ……, 𝑏𝑘bk, let 𝑓(𝑏)f(b) be the minimum number of classes Idnar has to ask to change their scene if he wants to avoid boring the audience.
Idnar hasn't decided which scenes will be allowed for the concert, so he wants to know the value of 𝑓f for each non-empty prefix of 𝑎a. In other words, Idnar wants to know the values of 𝑓(𝑎1)f(a1), 𝑓(𝑎1f(a1,𝑎2)a2), ……, 𝑓(𝑎1f(a1,𝑎2a2,……,𝑎𝑛)an).
Input
The first line contains a single integer 𝑛n (1≤𝑛≤2⋅1051≤n≤2⋅105) — the number of classes in the school.
The second line contains 𝑛n positive integers 𝑎1a1, 𝑎2a2, ……, 𝑎𝑛an (1≤𝑎𝑖≤1091≤ai≤109) — the lengths of the class scenes.
Output
Print a sequence of 𝑛n integers in a single line — 𝑓(𝑎1)f(a1), 𝑓(𝑎1f(a1,𝑎2)a2), ……, 𝑓(𝑎1f(a1,𝑎2a2,……,𝑎𝑛)an).
Examples
input
Copy
1
1
output
Copy
1
input
Copy
3
1 4 2
output
Copy
1 1 2
input
Copy
7
2 12 4 8 18 3 6
output
Copy
0 1 1 1 2 2 2
题意是给一个序列a,如果其中有一个区间[l, r]满足\(gcd(a_l, a_{l+1}...a_r)=r - l + 1\)则认为这个区间不好。同时,可以改变序列a的任意个数为任意值,求f(1), f(2)...f(n)。f(x)表示1到x这段a的子列最少需要改变的数的个数。
注意到,a个数的GCD一定不小于a+1个数的GCD,因此其具有单调性(满足二分条件)。且每次操作的那个数可以替换为任意值,那么就可以取一个大素数。且f值具有承袭性。那么考虑这样一个做法:
遍历1到n,设当前为i,lst为上一次进行操作的位置+1。如果当前a[i] = 1,必然要进行更改;否则基于上面提到的n个数GCD的性质,二分找[lst, i]这段区间是否存在某个字区间[x, i]满足\(gcd(a_x, a_{x+1}...a_i) = i-x+1\)。如果有的话则让f[i] = f[i - 1] + 1,同时lst更新为i + 1;如果没有则让f[i] = f[i - 1]即可。二分check可以用线段树查询区间GCD。
#include <iostream>
using namespace std;
int n, a[200005], f[200005];
struct SegmentTree {
int l, r, dat;
} t[200005 * 4];
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
void build(int p, int l, int r) {
t[p].l = l, t[p].r = r;
if(l == r) {
t[p].dat = a[l];
return;
}
int mid = (l + r) >> 1;
build(2 * p, l, mid);
build(2 * p + 1, mid + 1, r);
t[p].dat = gcd(t[2 * p].dat, t[2 * p + 1].dat);
}
int ask(int p, int l, int r, int L, int R) {
if(l >= L && r <= R) {
return t[p].dat;
}
int mid = (l + r) >> 1;
int ans = 0;
if(L <= mid) ans = ask(2 * p, l, mid, L, R);
if(R > mid) {
if(!ans) ans = ask(2 * p + 1, mid + 1, r, L, R);
else ans = gcd(ans, ask(2 * p + 1, mid + 1, r, L, R));
}
return ans;
}
int main() {
cin >> n;
int lst = 1;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, 1, n);
for(int i = 1; i <= n; i++) {
int l = lst, r = i, mid;
if(a[i] == 1) {
f[i] = f[i - 1] + 1;
lst = i + 1;
cout << f[i] << " ";
continue;
}
while(l < r) {
mid = (l + r) >> 1;
int gt = ask(1, 1, n, mid, i);
if(gt < i - mid + 1) l = mid + 1;
else if(gt == i - mid + 1) {
l = mid;
break;
}
else r = mid;
}
if(ask(1, 1, n, l, i) == i - l + 1) {
f[i] = f[i - 1] + 1;
lst = i + 1;
} else {
f[i] = f[i - 1];
}
cout << f[i] << " ";
}
return 0;
}