CF#687(div2) BCD

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(100n)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

1457C

想复杂了,因为同学好像都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,k1], 将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+ck,L[0,k1],cZ

倒着算贡献就行,有个边界没想清楚直接暴力+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; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值