yuwj  

codeforces 1055 div1 + div2

写在前面

这场打前准备睡一下,结果醒来就11点了,然后半个小时出的A的思路,所以决定不写了,睡觉

所以这一场都是补题,还好鸽了,不然要掉大分,目测,

加训,冲冲冲

guess 场,好吧,没什么好说的

A

反过来想,每次全部减少最小值,抹平操作加上就好了

void solve(){
    int n,x;
	cin >> n;
	set<int> st;
	for(int i=1;i<=n;++i) cin >> x,st.insert(x);
	cout << st.size()*2-1 << '\n';
}

B

vp的时候这个题想了3h整破防了

x 和 y 独立考虑

直接放到最边上算到各自两种情况的花费就好了,不用管另一个方向!独立独立独立!

卡死在独立上,一直想怎么处理剩下的,根本想不出来,其实根本不用管,靠

void solve(){
	int a,b,c,d;
	cin >> n >> a >> b >> c >> d;

	int ans = 0,t1=0,t2=0;
	if(a!=c) t1 = a<c?c:n-c;
	if(b!=d) t2 = b<d?d:n-d;
	ans = max(t1,t2);

	cout << ans << '\n';
}

C

C比B简单好多

两个事情,可行性,最小花费,一定是 len/3

特判,只有 010101010101 结构才会增加花费 1,先花费,在两个两个相邻减少完事

void solve(){
	cin >> n >> q;
	vector<int> num(n+1), cnt(n+1), sum(n+1);
	for(int i=1;i<=n;++i){
		cin >> x, num[i] = x, cnt[i] = cnt[i-1] + x;
	}

	// 相邻是否相等,以右边那个点作为标记点,表示 (i-1,i) 相邻相等
	// 查询区间 (l,l+1) (l+1,l+2)... (r-1,r) 相邻是否相等,实际上是 [l+1,r]
	// 就是 sum[r] - sum[l+1-1] = sum[r] - sum[l]
 	for(int i=2;i<=n;++i){ 
		sum[i] = sum[i-1] + (num[i] == num[i-1]);
	}

	while(q--){
		cin >> l >> r;
		int len = r-l+1, ans = -1;
		if((cnt[r] - cnt[l-1]) % 3 == 0 && len % 3 == 0){
			ans = len/3 + (sum[r] - sum[l] == 0);
		}
		cout << ans << '\n';
	}
}

D

xll %%%

思路:

结论:每个数字花费最高位 msb 作为基础值,设 msb = k,基础贡献 k

若,2^k + 2 <= x <= 2^(k+1) - 1, 则必然贡献 k+1

若,x = (2^k + 1),则每两个贡献一步

中间有 1 的后手一定可以让这个数变多一位;最后一位是 1 的后手可以把它转化为中间有 1

int get(int x){
	for(int i=31;i>=0;--i) if((x>>i)&1) return i;
	return 0;
}

void solve(){
	cin >> n >> q;
	For(i,1,n) cin >> num[i];
	vector<int> sum(n+1), b(n+1), add(n+1), pre(n+1);

	for(int i=1;i<=n;++i){
		x = get(num[i]);
		int flg0 = num[i] == (1 << x), flg1 = num[i] == (1 << x) + 1;
		sum[i] = sum[i-1] + x + (!flg0 && !flg1);
		pre[i] = pre[i-1] + flg1;
	}

	while(q--){
		cin >> l >> r;
		cout << sum[r] - sum[l-1] + (pre[r] - pre[l-1])/2 << '\n';
	}
}
posted on 2025-10-04 15:04  xiaowang524  阅读(22)  评论(0)    收藏  举报