1. 程式人生 > 其它 >Codeforces 1556, Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)

Codeforces 1556, Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)

終於藍了嗚嗚嗚
原來兩場四題就能上分 以後不棄賽了

A.

注意到2, 3操作不改變總和,1操作使得總和加上了一個偶數,故直接判斷總和是否為偶數即可。如果和為偶數,只要判斷c和d是否相等即可。注意0要判一下

B.

先判一下奇數和偶數的個數,在按順序分配位置就行。如果奇數和偶數個數相等,還得列舉奇數先放還是偶數先放。注意開ll。

C.

莫名其妙地ac了,不是很懂。

首先列舉左端點l和右端點r,用函式check(l,r)統計這兩個端點的貢獻(在l處開始,r處結束的合法括號序列的數量)。假設每一個左括號為1,右括號為-1,對序列求個字首和,方便判斷是否合法。

所有的從l開始,r結束的合法括號序列,不一定用了l和r中的每一個左右括號。

首先計算d=sum[r]-sum[l-1],以得出左右兩邊是否有多餘的括號,我們要捨去。之後再列舉\(l+1\)\(r-1\)的每一個位置\(i\),他們必須滿足\(sum[i]-sum[l-1]>=0\).統計這個差值的最小值,記為mx,其表示左邊l處最多能有幾個括號多出來。那麼答案至多有mx+1.注意當d>0時,這個值要減去d後才能用於更新mx。

之後保險起見,還得和左邊能貢獻的左括號數量,右邊能貢獻的右括號數量取min,注意此時也要把d的偏差加上去,具體見程式碼。

// Problem: C. Compressed Bracket Sequence
// Contest: Codeforces - Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/1556/problem/C
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
#define ll long long
int rd() {
    int s = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') {s = s * 10 + c - '0'; c = getchar();}
    return s * f;
}
int n, m, k;
ll tot;
ll c[maxn], ans, sum[maxn];
ll check(int l, int r) {
	ll d = sum[r]-sum[l-1], mx = 99999999999999999ll;
	for (int i = l+1; i < r; i += 2) {
		if (d <= 0)
			mx = min(mx, sum[i]-sum[l-1]);
		if (d > 0) 
			mx = min(mx, sum[i]-d-sum[l-1]);
	}
	if (mx < 0) return 0;
	//if (mx == 0) return 1;
	if (d == 0) return min(c[l], min(mx + 1ll, -c[r]));
	if (d < 0) return min(c[l], min(mx + 1ll, -c[r]+d));
	if (d > 0) return min(c[l]-d, min(mx+1ll, -c[r]));
}
int main() {
	n = rd();
	for (int i = 1; i <= n; i++) {
		c[i] = rd();
		if (i % 2 == 0) c[i] = -c[i];
		sum[i] = sum[i-1]+c[i];
	}
	for (int l = 1; l <= n; l += 2) {
		for (int r = l+1; r <= n; r += 2) {
			ans += check(l, r);
		}
	}
	printf("%lld\n", ans);
}

D.

\(a+b=a\&b+a|b\),用\(a+b,a+c,b+c\)可以求出\(abc\),已知\(a\)\(a\&b+a|b\)可以求\(b\),這樣直接求出所有的\(a[i]\)就行。

// Problem: D. Take a Guess
// Contest: Codeforces - Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/1556/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 7;
#define ll long long
int rd() {
    int s = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') {s = s * 10 + c - '0'; c = getchar();}
    return s * f;
}
int n, m, k, tot;
ll a[maxn];
typedef pair<int, int> pii;

#define mk make_pair
ll getPlus(int i, int j) {
	printf("or %d %d\n", i, j);
	fflush(stdout);
	ll orij = rd();
	printf("and %d %d\n", i, j);
	fflush(stdout);
	ll andij = rd();
	return orij + andij;
}
void get(int i, int j, int k) {
	ll pij = getPlus(i, j);
	ll pjk = getPlus(j, k);
	ll pik = getPlus(i, k);
	a[i] = (pij - pjk + pik) / 2ll;
	a[j] = (pjk - pik + pij) / 2ll;	
	a[k] = (pik - pij + pjk) / 2ll;	
}
int main() {
	n = rd(); k = rd();
	for (int i = 1; i <= n; i += 3) {
		if (i + 2 > n) break;
		get(i, i+1, i+2);
	}
	if (n % 3 == 1) {
		ll p1 = getPlus(1, n);
		a[n] = p1 - a[1];
	}
	if (n % 3 == 2) {
		ll p1 = getPlus(1, n-1);
		a[n-1] = p1 - a[1];
		ll p2 = getPlus(1, n);
		a[n] = p2 - a[1];
	}
	sort(a+1, a+n+1);
	printf("finish %lld\n", a[k]);
	return 0;
	//fflush(stdout);
}

注意每一行輸出之後要立刻fflush(stdout);