Codeforces Raif Round 1 (Div. 1 + Div. 2)题解

A.Box is Pull

题解:推箱子,特判同行同列即可,$O(1)$

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> 
 
#define ll long long
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define rev(i,a,b) for(int i = a; i >= b; i--)
 
using namespace std;
 
int x1, y, x2, y2, sum1, sum2, sum;
 
void solve() {
	cin >> x1 >> y >> x2 >> y2;
	if(x1 == x2) cout << abs(y2-y) << endl;
	else if(y == y2) cout << abs(x2-x1) << endl;
	else cout << 2 + abs(y2-y) + abs(x2-x1) << endl;
}
 
int main() {
	int T; cin >> T;
	while(T--) solve();
	return 0;
}

B.Belted Rooms

题解:看传送带是否能到达最左端或最右端,$O(n)$

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> 
 
#define ll long long
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define rev(i,a,b) for(int i = a; i >= b; i--)
 
using namespace std;
 
int n, sum;
 
bool q[300011], h[300011]; //q[i]=(右)能否从1到i, h[i]=(右)能否从i到 n
bool qq[300011], hh[300011]; 
 
char a[300011];
 
void solve() {
	cin >> n; sum = 0;
	for(int i = 1; i <= n; i++) scanf(" %c", &a[i]);
	q[1] = 1;
	for(int i = 2; i <= n; i++)
	if((a[i-1] == '>' || a[i-1] == '-') && q[i-1] == 1) q[i] = 1; 
	else q[i] = 0;
	h[n] = 1;
	for(int i = n-1; i >= 1; i--) 
	if((a[i] == '>' || a[i] == '-') && h[i+1] == 1) h[i] = 1;
	else h[i] = 0;
	qq[1] = 1;
	for(int i = 2; i <= n; i++)
	if((a[i-1] == '<' || a[i-1] == '-') && qq[i-1] == 1) qq[i] = 1;
	else qq[i] = 0; 
	hh[n] = 1;
	for(int i = n-1; i >= 1; i--) 
	if((a[i] == '<' || a[i] == '-') && hh[i+1] == 1) hh[i] = 1;
	else hh[i] = 0;
	for(int i = 1; i <= n; i++) {
		int las = i - 1, nxt = i + 1;
		if(las == 0) las = n;
		if(nxt > n) nxt = 1;
		if(a[i] == '-' || a[las] == '-') sum++;
		else {
			if(a[n] == '>' || a[n] == '-') {
				if(q[i] == 1 && h[i] == 1) {
					sum++; continue;
				}
			}
			if(a[n] == '<' || a[n] == '-') {
				if(qq[i] == 1 && hh[i] == 1) sum++;
			}
		}
	}
	cout << sum << endl;
}
 
int main() {
	int T; cin >> T;
	while(T--) solve();
	return 0;
}

C.ABBB

题解:我们分类讨论一下,发现消掉任意一个都是最优的,于是直接暴力,我写了个双向链表,$O(n)$

#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> 
 
#define ll long long
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define rev(i,a,b) for(int i = a; i >= b; i--)
 
using namespace std;
 
string s;
 
int n, pre[200011], nxt[200011], ans;
 
void solve() {
	cin >> s; n = s.size(); ans = n;
	nxt[0] = 1;
	for(int i = 1; i < n; i++) {
		pre[i] = i-1;
		nxt[i] = i+1;
	}
	pre[0] = n; 
	for(int i = 0; i < n; i = i) {
		if(s[i] == 'A' && s[nxt[i]] == 'B') {
			ans -= 2;
			nxt[pre[i]] = nxt[nxt[i]];
			pre[nxt[nxt[i]]] = pre[i];
			s[i] = s[nxt[i]] = ' ';
			if(pre[i] != n) i = pre[i];
			else i = nxt[nxt[i]];
			continue;
		}
		if(s[i] == 'B' && s[nxt[i]] == 'B') {
			ans -= 2;
			nxt[pre[i]] = nxt[nxt[i]];
			pre[nxt[nxt[i]]] = pre[i];
			s[i] = s[nxt[i]] = ' ';
			if(pre[i] != n) i = pre[i];
			else i = nxt[nxt[i]];
			continue;
		}
		i = nxt[i];
	}
	cout << ans << endl;
}
 
int main() {
	int T; cin >> T;
	while(T--) solve();
	return 0;
}

 


E.Carrots for Rabbits

题解:我们考虑用堆维护贪心,每次把切后收益最大的拿来切,注意这里的收益是原长度/段数,不是切后的长度/段数,$O(n \log n)$

#include <cstdio>
#include <queue>
#include <iostream>

#define ll long long
#define mkp make_pair
#define fr first
#define se second

using namespace std;

int n, k, a[1000011];

ll ans;

priority_queue <pair<ll, pair<int, int> > > q;

ll cal(int s1, int s2) {
	ll s = s1 % s2, p = s1 / s2;
	return (s2 - s) * p * p + s * (p+1) * (p+1);
}

int main() {
	scanf("%d%d", &n, &k); k -= n;
	for(int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
		ans += (ll)a[i] * (ll)a[i];
		q.push(mkp(cal(a[i], 1) - cal(a[i], 2), mkp(a[i], 1)));
	}
	for(int i = 1; i <= k; i++) {
		int sum = q.top().se.fr, num = q.top().se.se;
		ans -= q.top().fr;
		q.pop();
		q.push(mkp(cal(sum, num+1) - cal(sum, num+2), mkp(sum, num+1)));
	}
	cout << ans << endl;
	return 0;
}

 

posted @ 2020-11-19 09:51  huangxuanao  阅读(193)  评论(0)    收藏  举报