Codeforces Round #297 (Div. 2)

A. Vitaliy and Pie

给你一个字符串,奇数位上是小写字母,偶数位上是大写字母,小写字母表示钥匙的类型能打开对应大写字母的门,

大写字母表示门的种类,问之前还要买多少把钥匙,才能走完。

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <string>

#include <vector>

#include <cmath>

#include <queue>

#include <map>

#include <set>

using namespace std;

#define INF 1000000000

const int maxn = 1e5 + 10;

char str[maxn * 2];

int cnt[maxn * 2];

int main()

{

	int n;

	int ans = 0;

	memset(cnt, 0, sizeof(cnt));

	cin >> n;

	cin >> str + 1;

	for (int i = 1; i <= 2 * n - 2; i++){

		if (i & 1){

			int t = str[i] - 'a';

			cnt[t]++;

		}

		else{

			int t = str[i] - 'A';

			if (cnt[t] == 0){

				ans++; continue;

			}

			cnt[t]--;

		}

	}

	cout << ans << endl;

	return 0;

}

  

B. Pasha and String

给出一个字符串,然后m个东西,每个东西一个数字a[i], 将 [a[i],|s| - a[i]+1] 的区间内的字符串倒置,输出最后的串的样子。

因为是关于中点对称的,所以就记录每个点被覆盖的 次数,然后从左向中枚举,如果覆盖次数为奇数则交换a[i] ,a[s-i+1]。因为蠢了写了个线段树。。

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <string>

#include <vector>

#include <cmath>

#include <queue>

#include <map>

#include <set>

using namespace std;

#define INF 1000000000



#define  lson l,mid,rt<<1

#define  rson mid+1,r,rt<<1|1

const int maxn = 2 * 100000 + 10;

char str[maxn];

int color[maxn << 2];

void build(int l, int r, int rt)

{

	color[rt] = 0;

	if (l == r) return;

	int mid = (l + r) >> 1;

	build(lson); build(rson);

}



void down(int rt)

{

	if (color[rt]){

		color[rt << 1] ^= 1; color[rt << 1 | 1] ^= 1;

		color[rt] = 0;

	}

}

void update(int L, int R, int l, int r, int rt)

{

	if (L <= l&&r <= R){

		color[rt] ^= 1; return;

	}

	down(rt);

	int mid = (l + r) >> 1;

	if (L <= mid) update(L, R, lson);

	if (R>mid) update(L, R, rson);

}

int ask(int key, int l, int r, int rt)

{

	if (l == r) return color[rt];

	down(rt);

	int mid = (l + r) >> 1;

	if (key <= mid) return ask(key, lson);

	else return ask(key, rson);

}

int main()

{

	int m, a;

	scanf("%s", str + 1);

	int len = strlen(str + 1);

	cin >> m;

	build(1, len, 1);

	for (int i = 0; i<m; i++){

		scanf("%d", &a);

		update(a, len - a + 1, 1, len, 1);

	}

	for (int i = 1; i <= len / 2; i++){

		int t = ask(i, 1, len, 1);

		if (t) swap(str[i], str[len - i + 1]);

	}

	for (int i = 1; i <= len; i++)

		printf("%c", str[i]);

	cout << endl;

	return 0;

}

  

C. Ilya and Sticks

给出那么多根长度的火柴,每个火柴长度可以减1,也可以不减,四个火柴a,a,b,b类的可以拼成一个矩阵,问最后可以拼成的矩阵的和最大是多少?

从高到低排序,然后贪心搞下就好了。

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <string>

#include <vector>

#include <cmath>

#include <queue>

#include <map>

#include <set>

using namespace std;

typedef long long LL;

LL cmp(const LL &a, const LL &b)

{

	return a>b;

}

const int maxn = 1e5 + 10;

int a[maxn];

int q[maxn];

int main()

{

	int n;

	cin >> n;

	for (LL i = 1; i <= n; i++)

		cin >> a[i];

	sort(a + 1, a + n + 1, cmp);

	LL ans = 0;

	LL len = 0;

	LL l, r;

	for (LL i = 1; i<n; i++){

		q[len++] = a[i];

		if (a[i] == a[i + 1] || a[i] == a[i + 1] + 1){

			q[len++] = a[i + 1]; i++; continue;

		}

		len--;

	}

	for (LL i = 0; i<len - 3; i += 4){

		if (q[i] == q[i + 1]) l = q[i];

		else l = q[i + 1];

		if (q[i + 2] == q[i + 3]) r = q[i + 2];

		else r = q[i + 3];

		ans += l*r;

	}

	cout << ans << endl;

	return 0;

}

  

D. Arthur and Walls

给出一个n*m的图,*表示墙,.表示房间,问至少去了多少个*使得最后连通的房子中间没有墙这个东西,要求输出任意一副满足条件的图。

把分成2*2的小方格,如果2*2的小方格李有一个*,那么这个*就要变成. 。最后使得不存在有2*2的小方格内只有一个*。比赛的时候没有想到,

赛后还是没有想到,原本想的是把所有连通的最边界的四个顶点内的点全变为.。然后继续判,知道所有连通的图内不存在*为止。这个复杂度有点爆表。若是这个图合法,那么就不存在2*2的小方格里有一个*,分治搞,不好想,挺厉害的。为了省事,各种越界,a了。。无语。

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <string>

#include <vector>

#include <cmath>

#include <queue>

#include <map>

#include <set>

#include <stdlib.h>

#include <cstdlib> 

using namespace std;

#define INF 1000000000

int dx[] = { -1, -1, -1, 0, 1, 1, 1, 0 };

int dy[] = { -1, 0, 1, 1, 1, 0, -1, -1 };

const int maxn = 2222;

char str[maxn][maxn];

int vis[maxn][maxn];

int judge(int x, int y)

{

	if (str[x][y] == '.') return 0;

	if (str[x - 1][y - 1] == '.'&&str[x - 1][y] == '.'&&str[x][y - 1] == '.') return 1;

	if (str[x - 1][y] == '.'&&str[x - 1][y + 1] == '.'&&str[x][y + 1] == '.') return 1;

	if (str[x][y + 1] == '.'&&str[x + 1][y + 1] == '.'&&str[x + 1][y] == '.') return 1;

	if (str[x + 1][y] == '.'&&str[x + 1][y - 1] == '.'&&str[x][y - 1] == '.') return 1;

	return 0;

}

struct Node

{

	int x; int y;

};



queue<Node> q;

int main()

{

	memset(vis, 0, sizeof(vis));

	int n, m;

	cin >> n >> m;

	for (int i = 0; i < n; i++) scanf("%s", str[i]);

	for (int i = 0; i < n; i++){

		for (int j = 0; j < m; j++){

			if (judge(i, j)){

				Node t; t.x = i; t.y = j;

				q.push(t);

			}

		}

	}

	while (!q.empty()){

		Node  cur = q.front();

		int x = cur.x; int y = cur.y; q.pop();

		if (vis[x][y])continue;

		vis[x][y] = 1;

		//printf("%d %d\n",x,y);

		str[x][y] = '.';

		for (int i = 0; i < 8; i++){

			int xx = x + dx[i]; int yy = y + dy[i];

			if (xx >= 0 && yy >= 0 && xx<n&&yy<m){

				if (judge(xx, yy)){

					Node k; k.x = xx; k.y = yy;

					q.push(k);

				}

			}

		}

	}

	for (int i = 0; i < n; i++){

		for (int j = 0; j < m; j++) printf("%c", str[i][j]);

		cout << endl;

	}

	return 0;

}

  

E. Anya and Cubes

题意:n个数随便取,最多使得取得数里面的t个不超过k个变成其阶层的形式,使得最后和为s的方法数。

比赛的时候随便写了个暴力,就睡了。

此题用中途相遇法搞下,从中间折半,把左边搜到的值hash一下。在从右边搜,每次搜到一个S时,把hash表里值为 s - S且用的t不超过的k的的种类数相加.

赛后用map水过,注意用map<int,int> m; 用m[5] 判断 ,和m.count(5) ;判断5这个键值存在不存在时候,是有时间差距的,m[5]直接访问如果不存在,则会插入一个0进去,这样会多了许多无用的值。

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <iostream>

#include <string>

#include <vector>

#include <cmath>

#include <queue>

#include <map>

#include <set>

using namespace std;

#define INF 1000000000

//typedef __int64 LL;

typedef long long LL;

int up;

LL s;

LL k, len1, len2;

LL chart[100];

map<int, LL> m[30];

LL val;

int a[100];

LL jie(int x)

{

	LL ans = 1;

	for (int i = 1; i <= x; i++) ans *= i;

	return ans;

}



int gao(LL x)

{

	for (int i = 1; i <= 100; i++){

		if (jie(i)>x){

			return i - 1;

		}

	}

}



void init()

{

	for (int i = 1; i <= up; i++){

		chart[i] = jie(i);

	}

}



void dfs(int x, int ans, LL sum)

{

	if (x == len1 + 1){

		//printf("%d %d\n",k-ans,sum);

		m[k - ans][sum]++; return;

	}

	dfs(x + 1, ans, sum);

	if (sum + a[x] <= s) dfs(x + 1, ans, sum + a[x]);

	if (a[x] <= up&&chart[a[x]] + sum <= s&&ans){

		dfs(x + 1, ans - 1, sum + chart[a[x]]);

	}

}



void DFS(int x, int ans, LL sum)

{

	if (x == len2 + 1){

		//printf("%d %d\n",k-ans,sum);

		for (int i = 0; i <= ans; i++) if (m[i].count(s - sum)) val += m[i][s - sum];

		return;

	}

	DFS(x + 1, ans, sum);

	if (sum + a[x + len1] <= s) DFS(x + 1, ans, sum + a[x + len1]);

	if (a[x + len1] <= up&&chart[a[x + len1]] + sum <= s&&ans){

		DFS(x + 1, ans - 1, sum + chart[a[x + len1]]);

	}

}





int main()

{

	int n;

	val = 0;

	cin >> n >> k >> s;

	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);

	up = gao(s); init();

	len1 = n / 2; len2 = n - len1;

	dfs(1, k, 0); DFS(1, k, 0);

	cout << val << endl;

	return 0;

}

  

 

你可能感兴趣的:(codeforces)