2017-2018 ACM-ICPC, NEERC, Southern Subregional Contest, qualification stage

题目链接  传送门

Problem A

Problem B

Problem C

Problem D

Problem E

Problem F

Problem G

签到

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)

int n;
int c[10];
char s[10];
int ans = 0;

int main(){
	
	scanf("%d", &n);
	rep(i, 1, n){
		scanf("%s", s + 1);
		rep(j, 1, 7) c[j] += (s[j] == '1');
	}

	rep(i, 1, 7) ans = max(ans, c[i]);

	printf("%d
", ans);

	return 0;
}

  

Problem H

令$f[i]$为从左往右把$a[1]$到$a[i]$变成严格递增序列所需的最小代价。

$g[i]$为从右往左把$a[n]$到$a[i]$变成严格递减序列所需的最小代价。

$c[i]$为从左往右把$a[1]$到$a[i]$变成严格递增序列花费最小代价的时候$a[i]$的值。

$d[i]$为从左往右把$a[n]$到$a[i]$变成严格递减序列花费最小代价的时候$a[i]$的值。

枚举一下答案。

#include <bits/stdc++.h>

using namespace std;

#define	rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define	dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 1e5 + 10;

int n;
LL a[N], c[N], d[N], f[N], g[N];
LL ans;

int main(){

	scanf("%d", &n);
	rep(i, 1, n) scanf("%lld", a + i);

	c[1] = a[1];  f[1] = 0;
	rep(i, 2, n){
		if (a[i] > c[i - 1]){
			f[i] = f[i - 1];
			c[i] = a[i];
		}

		else{
			c[i] = c[i - 1] + 1;
			f[i] = f[i - 1] + c[i] - a[i];
		}
	}


	d[n] = a[n];  g[n] = 0;
	dec(i, n - 1, 1){
		if (a[i] > d[i + 1]){
			g[i] = g[i + 1];
			d[i] = a[i];
		}

		else{
			d[i] = d[i + 1] + 1;
			g[i] = g[i + 1] + d[i] - a[i];
		}
	}

	ans = 1e18;

	rep(i, 2, n - 1) ans = min(ans, f[i - 1] + g[i + 1] + (max(max(c[i - 1] + 1, d[i + 1] + 1), a[i])) - a[i]);

	ans = min(ans, f[n]);
	ans = min(ans, g[1]);

	printf("%lld
", ans);
	return 0;
}

  

Problem I

对于每一种噪音,上限为$2.6e7$

所以一种噪音最多传播到距离他$30$个单位的格子里;

直接暴力BFS即可。

#include <bits/stdc++.h>

using namespace std;

#define	rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define	dec(i, a, b)	for (int i(a); i >= (b); --i)
#define	MP		make_pair
#define	fi		first
#define	se		second

typedef long long LL;

const int N = 255;

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

struct node{
	int x, y;
	int dis;
	LL  cnt;
};

LL  q, p;
LL c[N][N];
int a[N][N];
int n, m;
char s[N];
int vis[N][N];
int ans = 0;


inline bool check(int x, int y){
	return x >= 1 && x <= n && y >= 1 && y <= m && a[x][y] != -1 && vis[x][y] == 0;
}

void solve(int x, int y){
	queue <node> qq;
	queue < pair <int, int> > clr;
	while (!qq.empty()) qq.pop();
	qq.push({x, y, 0, q * a[x][y]});
	vis[x][y] = 1;
	clr.push(make_pair(x, y));
	while (!qq.empty()){
		node now = qq.front(); qq.pop();
		int x = now.x, y = now.y;
		int dis = now.dis;
		LL cnt = now.cnt;
		c[x][y] += cnt;

		rep(i, 0, 3){
			int nx = x + dx[i], ny = y + dy[i];
			if (check(nx, ny)){
				int newdis = dis + 1;
				LL  newcnt = cnt / 2;
				if (newcnt > 0){
					qq.push({nx, ny, newdis, newcnt});
					vis[nx][ny] = 1;
					clr.push(MP(nx, ny));
				}
			}
		}
	}

	while (!clr.empty()){
		int x = clr.front().fi, y = clr.front().se;
		vis[x][y] = 0;
		clr.pop();
	}
}


int main(){

	scanf("%d%d%lld%lld", &n, &m, &q, &p);
	rep(i, 1, n){
		scanf("%s", s + 1);
		rep(j, 1, m){
			if (s[j] >= 'A' && s[j] <= 'Z') a[i][j] = (int)s[j] - 64;
			else if (s[j] == '.') a[i][j] = 0;
			else a[i][j] = -1;
		}
	}

	rep(i, 1, n) rep(j, 1, m) if (a[i][j] > 0) solve(i, j);
	rep(i, 1, n) rep(j, 1, m) if (c[i][j] > p) ++ans;
	printf("%d
", ans);
	return 0;
}

  

Problem J

Problem K

Problem L

构造题。

读入稍微有点麻烦

设$c[i][j]$为假设i和j之间有边并且如果把$i$和$j$断开的话那么$j$这个连通块的大小。

显然当$c[i][j] + c[j][i] = n$的时候$i$和$j$之间就真的有边了。

无解的情况为某个点的给定度数和实际做出来的度数不一样。

#include <bits/stdc++.h>

using namespace std;

#define	rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define	dec(i, a, b)	for (int i(a); i >= (b); --i)

const int N = 1010;

int c[N][N], f[N][N];
int deg[N];
int n;
int x, y;

int main(){

	scanf("%d", &n);
	rep(i, 1, n){
		while (scanf("%d:", &x)){
			++deg[i];
			rep(j, 1, x - 1){
				scanf("%d,", &y);
				f[i][y] = x;
			}

			scanf("%d", &y);
			f[i][y] = x;
			if (getchar() != '-') break;
		}
	}
	
	rep(i, 1, n - 1){
		rep(j, i + 1, n){
			if (f[i][j] + f[j][i] == n) c[i][j] = c[j][i] = 1;
		}
	}


	rep(i, 1, n){
		rep(j, 1, n) if (c[i][j]) --deg[i];
		if (deg[i]) return 0 * puts("-1");
	}

	printf("%d
", n - 1);
	rep(i, 1, n - 1){
		rep(j, i + 1, n) if (c[i][j]) printf("%d %d
", i, j);
	}

	return 0;
}

Problem M

签到

#include <bits/stdc++.h>

using namespace std;

#define	rep(i, a, b)	for (int i(a); i <= (b); ++i)


int a[200010];
int n;
set <int> s;

int main(){


	scanf("%d", &n);
	rep(i, 1, n) scanf("%d", a + i);
	

	rep(i, 1, n - 1) s.insert(a[i + 1] - a[i]);
	

	if ((int)s.size() == 1) printf("%d
", a[n] - a[n - 1] + a[n]);
	else printf("%d
", a[n]);
	return 0;
}
原文地址:https://www.cnblogs.com/cxhscst2/p/8016396.html