zoukankan      html  css  js  c++  java
  • 比赛-xxxxxyt学姐的训练赛 (25 Aug, 2018)

    NKOJ 上可以搜索到题目。

    A. Candies##

    BFS 一下就可以了。注意这题不满足二分性质。

    #include <cstdio>
    #include <queue>
    
    using namespace std;
    
    struct node {
    	int x, y;
    	node(int x = 0, int y = 0):
    		x(x), y(y) { }
    };
    
    queue<node> Q;
    int A[105][105], V, N, M, Cnt;
    int nxt[4][2] = {0,1,0,-1,1,0,-1,0};
    bool mk[105][105], mk2[105][105];
    
    void check(int x, int y)
    {
    	if (1 <= x && x <= N && 1 <= y && y <= M && A[x][y] >= V && !mk[x][y])
    		Q.push(node(x, y)), mk[x][y] = 1, ++Cnt;
    	return;
    }
    
    bool test()
    {
    	Cnt = 0;
    	for (int i = 1; i <= N; ++i)
    		for (int j = 1; j <= M; ++j)
    			mk[i][j] = 0;
    	for (int i = 1; i <= N; ++i) {
    		check(i, 1);
    		check(i, M);
    	}
    	for (int j = 2; j < M; ++j) {
    		check(1, j);
    		check(N, j);
    	}
    	while (!Q.empty()) {
    		node p = Q.front();
    		Q.pop();
    		for (int i = 0; i < 4; ++i)
    			check(p.x + nxt[i][0], p.y + nxt[i][1]);
    	}
    	
    	if (Cnt == N * M) return 0;
    	
    	bool flag = 0;
    	
    	for (int i = 1; i <= N; ++i) {
    		for (int j = 1; j <= M; ++j) {
    			if (!mk[i][j]) {
    				Q.push(node(i, j));
    				flag = 1;
    				break;
    			}
    		}
    		if (flag) break;
    	}
    	
    	for (int i = 1; i <= N; ++i)
    		for (int j = 1; j <= M; ++j)
    			mk2[i][j] = 0;
    	int tot = 0;
    	while (!Q.empty()) {
    		node p = Q.front();
    		Q.pop();
    		for (int i = 0; i < 4; ++i) {
    			int x = p.x + nxt[i][0], y = p.y + nxt[i][1];
    			if (1 <= x && x <= N && 1 <= y && y <= M && !mk[x][y] && !mk2[x][y])
    				Q.push(node(x, y)), mk2[x][y] = 1, ++tot;
    		}
    	}
    	return tot + Cnt < N * M;
    }
    
    int main()
    {
    	scanf("%d%d", &N, &M);
    	for (int i = 1; i <= N; ++i)
    		for (int j = 1; j <= M; ++j)
    			scanf("%d", &A[i][j]);
    	for (V = 100; V >= 1; --V) {
    		if (test()) {
    			printf("%d
    ", V);
    			return 0;
    		}
    	}
    	printf("-1
    ");
    	return 0;
    }
    

    B. Cards##

    BZOJ3262 陌上花开 弱化版,没有相同元素。三位偏序问题(第一维排序,第二维分治,第三维数据结构)。同时这题非常良心,不同数据采用不同算法,即暴力 dp 或者 topsort 可过 60 分的数据, (O(n^2)) ;剩下的 40 分是一个二维偏序,用 cdq 分治,或者对第一维排序后 (O(n cdot log n)) 求最长不降子序列即可。

    60 + 40 分的代码

    #include <stdio.h>
    #include <vector>
    #include <queue>
    #include <algorithm>
    
    using namespace std;
    
    const int _N = 1020000;
    
    int ind[_N], len[_N], N;
    vector<int> G[_N];
    queue<int> Q;
    
    struct data {
    	int a, b, c;
    	bool operator < (const data &tmp)
    	const
    	{
    		return a <= tmp.a && b <= tmp.b && c <= tmp.c;
    	}
    } A[_N];
    
    bool cmp(data a, data b)
    {
    	return a.a < b.a || a.a == b.a && a.b < b.b;
    }
    
    void fun1()
    {
    	int ans;
    	sort(A + 1, A + 1 + N, cmp);
    	len[ans = 1] = A[1].b;
    	for (int i = 2; i <= N; ++i) {
    		if (A[i].b >= len[ans]) {
    			len[++ans] = A[i].b;
    		} else {
    			int t = upper_bound(len + 1, len + 1 + ans, A[i].b) - len;
    			len[t] = A[i].b;
    		}
    	}
    	printf("%d
    ", ans);
    	return;
    }
    
    int main()
    {
    	scanf("%d", &N);
    	for (int i = 1; i <= N; ++i)
    		scanf("%d%d%d", &A[i].a, &A[i].b, &A[i].c);
    	if (N >= 1055) {
    		fun1();
    		return 0;
    	}
    	for (int i = 1; i <= N; ++i) {
    		for (int j = 1; j <= N; ++j) {
    			if (i != j && A[i] < A[j])
    				G[i].push_back(j), ++ind[j];
    		}
    	}
    	for (int i = 1; i <= N; ++i)
    		if (!ind[i]) Q.push(i), len[i] = 1;
    	while (!Q.empty()) {
    		int p = Q.front();
    		Q.pop();
    		for (int i = G[p].size() - 1; i >= 0; --i) {
    			int v = G[p][i];
    			if (!--ind[v]) Q.push(v), len[v] = len[p] + 1;
    		}
    	}
    	int ans = 0;
    	for (int i = 1; i <= N; ++i)
    		ans = max(ans, len[i]);
    	printf("%d
    ", ans);
    	return 0;
    }
    

    C. Pets##

    分析一下可以发现两部分的图中均不能有环, topsort 判一下是否有环即可。然后问题转化成要把第二部分链中的节点插入到第一部分的链中( topsort 之后肯定保证是一条链)。 (f_{i,j}) 表示考虑把第二部分链第 (j) 个点插入到第一部分链第 (i)(i+1) 个点中间,则:

    [f_{i,j} = max(f_{i-1,j},f_{i,j-1}+[t]) ]

    事件 (t) 是指第二部分第 (j) 个点可以合法插入,为真条件是第一部分链 ([1,i]) 这些点均有到 (j) 的边,且 ([i+1,m]) 这些点均没有到 (j) 的边(这也意味着 (j) 到这些点有边)。这个可以 (O(n^2)) 预处理。答案是 (f_{m,n-m})

    #include <stdio.h>
    #include <vector>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    
    using namespace std;
    
    const int _N = 1200;
    
    int top[2][_N], f[_N][_N], ind[_N], pos[_N], N, M;
    bool mk[_N], G[_N][_N];
    queue<int> Q;
    
    int topsort(bool t)
    {
    	for (int i = 1; i <= N; ++i) ind[i] = 0;
    	for (int i = 1; i <= N; ++i)
    		for (int j = 1; j <= N; ++j)
    			if (mk[i] ^ t && mk[j] ^ t && G[i][j])
    				++ind[j];
    	for (int i = 1; i <= N; ++i)
    		if (mk[i] ^ t && !ind[i]) Q.push(i);
    	int cnt = 0;
    	while (!Q.empty()) {
    		int p = Q.front();
    		Q.pop(), top[t][++cnt] = p;
    		for (int i = 1; i <= N; ++i)
    			if (mk[i] ^ t && G[p][i] && !--ind[i])
    				Q.push(i);
    	}
    	return cnt;
    }
    
    int dfs(int i, int j)
    {
    	if (~f[i][j]) return f[i][j];
    	if (!j) return f[i][j] = 0;
    	if (!i) return f[i][j] = dfs(i, j - 1) + (pos[j] == i);
    	
    	return f[i][j] = max(dfs(i - 1, j), dfs(i, j - 1) + (pos[j] == i));
    }
    
    int main()
    {
    	scanf("%d%d", &N, &M);
    	for (int i = 1; i <= N; ++i)
    		for (int j = 1; j <= N; ++j)
    			scanf("%d", &G[i][j]);
    	for (int t, i = 1; i <= M; ++i)
    		scanf("%d", &t), mk[t] = 1;
    	if (topsort(1) != N - M || topsort(0) != M) {
    		printf("NO
    ");
    		return 0;
    	}
    	for (int i = 1; i <= N - M; ++i) {
    		int j, t;
    		for (j = 1; j <= M; ++j)
    			if (!G[top[0][j]][top[1][i]]) break;
    		for (t = j; j <= M; ++j)
    			if (G[top[0][j]][top[1][i]]) break;
    		pos[i] = j == M + 1 ? t - 1 : -1;
    	}
    	memset(f, -1, sizeof f);
    	printf("YES %d
    ", dfs(M, N - M));
    	return 0;
    }
    
  • 相关阅读:
    Educational Codeforces Round 20 D. Magazine Ad
    Educational Codeforces Round 20 C. Maximal GCD
    紫书第三章训练2 暴力集
    Educational Codeforces Round 20 B. Distances to Zero
    Educational Codeforces Round 20 A. Maximal Binary Matrix
    紫书第三章训练1 D
    紫书第一章训练1 D -Message Decoding
    HAZU校赛 Problem K: Deadline
    Mutual Training for Wannafly Union #8 D
    紫书第三章训练1 E
  • 原文地址:https://www.cnblogs.com/ghcred/p/9534448.html
Copyright © 2011-2022 走看看