1. 程式人生 > 其它 >Codeforces Round #796 (Div2) A~F題解

Codeforces Round #796 (Div2) A~F題解

https://codeforces.com/contest/1688

打的稀碎,就不說結果了

A題

題意:
給定一個正整數\(x\),找到最小的正整數\(y\),使得\(x AND y > 0\)\(x XOR y > 0\)

思路:
要使得\(x AND y > 0\), 顯然\(x和y\)要至少有一個二進位制位相同。
要使得\(x XOR y > 0\), 顯然\(x和y\)要至少有一個二進位制位不同。
在此基礎上找到最小的\(y\)即可。

void solve() {
	int x;
	cin >> x;
	int res = x & (-x);
	if(res == x) {
		for(int i = 0 ; i <= 30 ; i ++) {
			if(!(res & (1 << i))) {
				res |= (1 << i);
				break;
			}
		}		
	}
 
	cout << res << "\n";
}

B題

題意:
給定一個數組\(a\),希望用最少的操作代價,使得\(a\)中所有元素均為奇數。可選操作為:
花費\(1\)的代價,將\(a\)中兩個元素合併為它們的和。
花費\(1\)的代價,將一個偶數元素的值變為原來的一半。

思路:
這個sb題我都能wa兩發,太菜了。
如果陣列中有奇數的話,顯然我直接將所有偶數合併,然後再加個奇數,就沒有偶數了。
如果陣列中全為偶數的話,我優先把除二次數最小就能變成奇數的偶數變成奇數,然後同上操作即可。

int a[N];
 
void solve() {
	int n;
	cin >> n;
	for(int i = 1 ; i <= n ; i ++) cin >> a[i];
	int s = 0, res = 0;
	int mind = 1e9;
	for(int i = 1 ; i <= n ; i ++){
		if((a[i] & 1) == 0) // 偶數的話
		{
			res ++;
			int cnt = 0;
			while(a[i] && (a[i] & 1) == 0) {
				cnt ++;
				a[i] >>= 1;
			}
			mind = min(mind, cnt);			
		}
		
	} 
 
	if(res == n) res = res - 1 + mind;
 
	cout << res << "\n";
}

C題

題意:
初始時有一個長度為\(1\)的由小寫字母組成的字串\(s\)
它進行了\(n\)次操作,每次操作選擇\(s\)的一個子串\(t_1\)和任意字串\(t_2\)
\(s\)中的子串\(t_1\)替換成\(t_2\)。現在亂序給出這\(n\)個操作對應的兩個字串,以及\(s\)最終字串\(sfinal\)
求出初始的\(s\)。保證答案存在且唯一。

思路:
這個題真的是一點思路都沒有,還是後面參考了別人的題解,才寫的。

我只能說太女少了!

int cnt[30];
 
void solve() {
	memset(cnt, 0, sizeof cnt);
	int n;
	cin >> n;
	for(int i = 1 ; i <= n * 2 + 1 ; i ++) {
		string s;
		cin >> s;
		for(auto c : s) cnt[c - 'a'] ++;
	}
	for(int i = 0 ; i < 26 ; i ++)
		if(cnt[i] & 1){
			cout << (char)(i + 'a') << "\n";
			return;
		}
}

D題

題意:

思路:

int a[N];
 
void solve() {
	int n, k;
	cin >> n >> k;
	for(int i = 1 ; i <= n ; i ++) cin >> a[i];
	int maxv = 0, s = 0; 
	int l = 1;
	for(int i = 1 ; i <= n ; i ++) {
		s += a[i];
		if(i - l + 1 > k) s -= a[l ++];
		maxv = max(maxv, s);
	}
	int res = maxv;
	if(k <= n) res += k * (k - 1) / 2;
	else {
		int p = k - 1;
		int c = p - n + 1;
		res += p * (p + 1) / 2 - c * (c + 1) / 2 + c;
	}
	cout << res << "\n"; 
}

E題

題意:

思路:

char s[N];
pii edge[N];
 
bool cmp(pii a, pii b){
	return a.x < b.x;
}
 
void solve() {
	int n, m;
	cin >> n >> m;
	for(int i = 0 ; i < m ; i ++) s[i] = '0';
	for(int i = 0 ; i < m ; i ++) {
		s[i] = '1';
		cout << "? " << s << endl;
		int len;
		cin >> len;
		edge[i] = {len, i};
		s[i] = '0';
	}
	sort(edge, edge + m, cmp);
	
	int minv = 0;
	for(int i = 0 ; i < m ; i ++) {
		int l = edge[i].x, now = edge[i].y;
		s[now] = '1';
		cout << "? " << s << endl;
		int len;
		cin >> len;
		if(minv + l == len) minv = len;
		else s[now] = '0';
	}
	cout << "! " << minv << endl;
}

F題

題意:

思路:

int a[N];
int b[N];
int c[N];
int s[N];
 
void solve() {
	int n, m;
	cin >> n >> m;
	for(int i = 1 ; i <= n ; i ++) cin >> a[i];
	set<int> st;
	for(int i = 1 ; i <= n ; i ++) {
		cin >> b[i];
		c[i] = a[i] - b[i];
		s[i] = s[i - 1] + c[i];
		if(s[i]) st.insert(i);
	}
	
	queue<pii> que;
	vector<vector<pii>> v(n + 1);
	for(int i = 1 ; i <= m ; i ++) {
		int l, r;
		cin >> l >> r;
		if(!s[l - 1] && !s[r]) que.push({l, r});
		else {
			v[l - 1].push_back({l, r});
			v[r].push_back({l, r});
		}
	}
	
	while(!que.empty()) {
		auto u = que.front();
		que.pop();
		auto iter = st.lower_bound(u.x);
		
		while(iter != st.end() && *iter <= u.y) {
			s[*iter] = 0;
			for(auto ints : v[*iter]) {
				if(!s[ints.x - 1] && !s[ints.y]) {
					que.push(ints);
				}
			}
			st.erase(iter ++);
		}
		
	}
	
	if(st.empty()) {
		cout << "YES\n";
	} else {
		cout << "NO\n";
	}
}