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;
}

  

 

posted on 2015-03-31 09:57  一个西瓜  阅读(137)  评论(0编辑  收藏  举报

导航