题解 Codeforces Round #806 (Div. 4)

题解 Codeforces Round #806 (Div. 4)

比赛链接

SolvedTimePenalty
7/783min224

太菜了。

A. YES or YES?

//A
#include <cstdio>

char s[10];
int t;

int main(){
	scanf("%d", &t);
	while(t--){
		scanf("%s", s);
		if((s[0] == 'Y' || s[0] == 'y') && (s[1] == 'E' || s[1] == 'e')
		   && (s[2] == 'S' || s[2] == 's')){
		   	puts("YES");
		   } else puts("NO");
	}
	return 0;
}

B. ICPC Balloons

c n t cnt cnt 数组记录每个字母是否为第一次出现。

//B
#include <cstdio>
#include <cstring>

int t, n;
char s[60], cnt[30];

int main(){
	scanf("%d", &t);
	while(t--){
		memset(cnt, 0, sizeof(cnt));
		scanf("%d", &n);
		scanf("%s", s+1);
		int ans= 0 ;
		for(int i = 1; i <= n; ++ i){
			if(cnt[s[i]-'A']){
				ans += 1;
			} else {
				cnt[s[i]-'A'] = 1;
				ans += 2;
			}
		}
		printf("%d\n", ans);
	}
}

C. Cypher

注意 UD 反着来。

//C
#include <cstdio>

const int N = 110;
int t, n, a[N], b;
char s[N];

int main(){
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		for(int i = 1; i <= n; ++ i){
			scanf("%d", &a[i]);
		}
		for(int i = 1; i <= n; ++ i){
			scanf("%d", &b);
			scanf("%s", s+1);
			for(int j = 1; j <= b; ++ j){
				if(s[j] == 'D'){
					if(a[i] == 9){
						a[i] = 0;
					} else ++ a[i];
				} else {
					if(a[i] == 0){
						a[i] = 9;
					} else -- a[i];
				}
			}
		}
		for(int i = 1; i <= n; ++ i){
			printf("%d ", a[i]);
		}
		puts("");
	}
	return 0;
}

D. Double Strings

暴力,开 map 记录每个串出没出现过。先读完然后再判断。

//D
#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int t, n;
string s[N];
map<string, int> mp;

int main(){
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		mp.clear();
		for(int i = 1; i <= n; ++ i){
			cin >> s[i];
			mp[s[i]] = 1;
		}
		for(int i = 1; i <= n; ++ i){
			bool flg = false;
			int k = s[i].size();
			for(int j = 1; j < k; ++ j){
				string a = s[i].substr(0, j);
				string b = s[i].substr(j, k);
				if(mp[a] && mp[b]) flg = true;
			}
			if(flg) putchar('1');
			else putchar('0');
		}
		puts("");
	}
}

E. Mirror Grid

四个对应点的位置分别是 ( i , j ) , ( j , n − i + 1 ) , ( n − i + 1 , n − j + 1 ) , ( n − j + 1 , i ) (i,j),(j,n-i+1),(n-i+1,n-j+1),(n-j+1,i) (i,j),(j,ni+1),(ni+1,nj+1),(nj+1,i)

判一下里面 1 少还是 0 少就行。

我也不知道为什么我的程序里答案要 / 4 /4 /4

//E
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 110;
int t, n;
char a[N][N];

int main(){
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		int ans = 0;
		for(int i = 1; i <= n; ++ i){
			scanf("%s", a[i] + 1);
		}
		for(int i = 1; i <= n; ++ i){
			for(int j = 1; j <= n; ++ j){
				int cnt = 0;
				if(a[i][j] == '1'){
					++ cnt;
					a[i][j] = '1';
				}
				if(a[j][n-i+1] == '1'){
					++ cnt;
					a[j][n-i+1] = '1';
				}
				if(a[n-i+1][n-j+1] == '1'){
					++ cnt;
					a[n-i+1][n-j+1] = '1';
				}
				if(a[n-j+1][i] == '1'){
					++ cnt;
					a[n-j+1][i] = '1';
				}
				if(cnt){
					ans += min(cnt, 4-cnt);
				}
			}
		}
		printf("%d\n", ans / 4);
	}
}

F. Yet Another Problem About Pairs Satisfying an Inequality

f i = [ a i < i ] f_i = [a_i<i] fi=[ai<i]

遍历数组,若发现 a i < i a_i<i ai<i,则答案累加上 ∑ j = 1 i − 1 f j \sum_{j=1}^{i-1}f_j j=1i1fj

程序里使用树状数组维护了 f f f

//F
#include <cstdio>

const int N = 2e5 + 10;
int t, n, a[N];

#define lb(x) (x&-x)
long long bit[N];
void add(int x, long long v){
	while(x <= n){
		bit[x] += v;
		x += lb(x);
	}
}
long long ask(int r){
	long long ans = 0;
	while(r){
		ans += bit[r];
		r -= lb(r);
	}
	return ans;
}

int main(){
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		long long ans = 0;
		for(int i = 1; i <= n; ++ i){
			scanf("%d", &a[i]);
			if(a[i] < i){
				add(i, 1);
				if(a[i]) ans += ask(a[i]-1);
//				printf("%d %d\n", i, ask(a[i]));
			}
		}
		printf("%lld\n", ans);
		for(int i = 1; i <= n; ++ i){
			bit[i] = 0;
		}
	}
	return 0;
}

G. Good Key, Bad Key

可以很快的写出一个 O ( n 2 ) O(n^2) O(n2) 的 dp,但是没啥用。

发现性质:最优解必定是用好钥匙开前面多少个箱,其它用坏钥匙开。即不存在一个使用好钥匙开的箱子,前面有箱子用坏钥匙开

然后计算出一个 g g g 数组, g i g_i gi 表示第 i ∼ n i\sim n in 号箱子全都用坏钥匙开能获得的金币数。答案即为:

max ⁡ i = 0 n ( ∑ j = 1 i a j + g i + 1 ) \max\limits_{i=0}^n \left(\sum_{j=1}^i a_j + g_{i+1}\right) i=0maxn(j=1iaj+gi+1)

//G
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 1e5 + 10;
int t, n;
ll k, a[N], g[N];

int main(){
	scanf("%d", &t);
	while(t--){
		scanf("%d%lld", &n, &k);
		for(int i = 1; i <= n; ++ i){
			scanf("%lld", &a[i]);
			ll p = a[i];
			for(int j = i; j; -- j){
				p >>= 1;
				if(!p) break;
				g[j] += p;
			}
		}
		ll ans = g[1], sum = 0;
		for(int i = 1; i <= n; ++ i){
			sum += a[i] - k;
//			printf("%lld %lld %lld\n", ans, sum, g[i]);
			ans = max(ans, sum + g[i+1]);
		}
		memset(g, 0, sizeof(g));
		printf("%lld\n", ans);
	}
	return 0;
}

后记:比赛结束后突然发现 G 用了 memset,应该没啥问题吧。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值