CF#687(div2)
如果E小于2000,到时候再补,先挖个坑
是补题所以把A跳了,
别老是自己给自己乱加边界情况行不行
别乱听tag,不过正式应该没人给我乱报tag(那没事了
B
直接暴力,判断每次将 c i c_i ci作为最后颜色的答案, O ( 100 ∗ n ) 1 e 7 O(100 * n) \,\,1e7 O(100∗n)1e7
#include <bits/stdc++.h>
using namespace std;
int n, k;
const int maxn = 1e5 + 10;
int a[maxn];
int getRes(int co) {
int res = 0;
int i = 1;
while(i <= n) {
if(i > n) break;
if(a[i] == co) {
++ i;
}
else {
++ res;
i = i + k;
}
}
return res;
}
int main() {
int T;
cin >> T;
while(T --) {
// int n, k;
cin >> n >> k;
for(int i = 1; i <= n; ++ i) {
cin >> a[i];
}
int ans = n;
for(int i = 1; i <= 100; ++ i) {
int res = getRes(i);
ans = min(ans, res);
}
cout << ans << endl;
}
return 0;
}
C - Bouncing Ball
想复杂了,因为同学好像都wa挺多发的,说是边界很多
第一眼看到题: 这不水题吗
一交:wa3
谢谢您。
然后加了个特判,继续wa,
发现有个地方没考虑清楚,改了下,还是wa
把第二次加的特判删了就a了,(??
刚开始的想法是根据第一个点为 p o s = p + L , L ∈ [ 0 , k − 1 ] pos = p + L, L \in [0, k -1] pos=p+L,L∈[0,k−1], 将n个坐标分成k组,对于每组单独去计算贡献,
注意到x可能比y大很多,可能会有不用x全靠y贡献,然后写了个
O
(
1
)
O(1)
O(1)那种式子,在某些情况下直接把答案更新成负数那种,真有我的,丢人就不摆出来了
然后发现第一个点也有可能是 p o s = p + L + c ∗ k , L ∈ [ 0 , k − 1 ] , c ∈ Z ∗ pos = p + L + c * k, L \in [0, k -1],c \in Z^* pos=p+L+c∗k,L∈[0,k−1],c∈Z∗
倒着算贡献就行,有个边界没想清楚直接暴力+10,好像不用加也是对的(?刚开始有个自测样例可能不知道出了啥问题,我挨打,
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
ll a[maxn];
int main() {
int T;
cin >> T;
while(T --) {
ll n, p, k;
cin >> n >> p >> k;
char ch;
for(int i = 1; i <= n; ++ i) {
cin >> ch;
if(ch == '0') {
a[i] = 0ll;
}
else {
a[i] = 1ll;
}
}
ll x, y;
cin >> x >> y;
ll ans = 1e18;
for(ll l = 0ll; l < k; ++ l) {
int tot = 0;
ll cc = (n - (p + l) + k - 1) / k;
for (ll c = cc + 10; c >= 0; -- c) { //+10 : 边界没考虑清楚的产物
ll pos = p + l + c * k;
if(pos > n) continue;
if(a[pos] == 0) tot ++;
ll res = tot * x + (pos - p) * y;
ans = min(ans, res);
}
}
cout << ans << endl;
}
return 0;
}
D - XOR-gun
题意 :给出一个保证是不减的数列, a i ∈ [ 1 , 1 0 9 ] a_i \in [1, 10^9] ai∈[1,109]有一种操作是把数列中任意两个连续的数替换成他们的xor,问是否能经过一定次数的操作使数列不再递减,
刚开始有个地方想错了:觉得只要出现两个相同的数,因为他们xor等于0,就可以通过一次操作得到目标数列,简直就是乱给自己加边界情况,
3
1 1 2
我自己秒给自己卡了,还贡献wa,丢人
另一个错误的点:公 开 处 刑
for(int i = 1; i <= n; ++ i) {
dp[i] = max(a[i], dp[i - 1] ^ a[i]);
}
for(int i = n; i >= 0; -- i) {
f[i] = min(a[i], f[i + 1] ^ a[i]);
}
我为什么觉得 dp[i] := 包含i的最大的连续xor值 能这样算
虽然但是,对不起,这题怎么会是dp啊,真的有被同学的tag给带偏(bushi
此时还不知道是几分的题,反正把我卡没了就对了
很妙:
-
和每个数的最高二进制位是第几位有关,如果有连续三个数的最高二进制位相同,则前两个xor最高位消掉一定会得到小于第三个数的数,贡献为1
-
xorr[] 是前缀xor和,根据xor两次相当于没有xor的性质,求一段连续的比如[l,r]的xor相当于是
xor[r] ^ xor[l - 1]
-
不符合第一个点的数据量将会非常小,因为相当于每个数的二进制最高位只能有两个数,总数据量不会超过70,可以 O ( n 3 ) O(n^3) O(n3)暴力端点求解,
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int a[maxn], xorr[maxn];
int bits[maxn];
int getRes(int x) {
int res = 0;
while(x) {
res ++;
x >>= 1;
}
return res;
}
int main() {
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++ i) {
scanf("%d", &a[i]);
xorr[i] = xorr[i - 1] ^ a[i];
bits[i] = getRes(a[i]);
}
for(int i = 3; i <= n; ++ i) {
if(bits[i - 2] == bits[i - 1] && bits[i - 1] == bits[i]) {
cout << 1;
return 0;
}
}
int ans = 1e9;
for(int i = 1; i <= n; ++ i) {
for(int l = i; l > 0; -- l) {
for(int r = i + 1; r <= n; ++ r) {
//if( r - l - 1 > ans) break;
int x = xorr[i] ^ xorr[l - 1];
int y = xorr[r] ^ xorr[i];
if(x > y) {
ans = min(ans, r - l - 1);
break;
}
}
}
}
if(ans == 1e9) {
cout << -1;
}
else {
cout << ans;
}
return 0;
}