zoukankan      html  css  js  c++  java
  • TJOI2013 DAY2

    第一题:明显先处理出最终序列,然后用线段树求解。处理最终序列可以用二分加树状数组(时间复杂度log2n, 用平衡树也可以搞。。。)。

    /* 
     * Problem: TJOI2013-day2-Sequence
     * Author: Shun Yao
     */
    
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <assert.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <math.h>
    #include <time.h>
    
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #include <bitset>
    #include <utility>
    #include <iomanip>
    #include <numeric>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    //using namespace std;
    
    const int MAXN = 100010;
    
    int getInt() {
    	static char ch, f;
    	static int ret;
    	f = 1;
    	while (ch = getchar(), ch < '0' || ch > '9')
    		if (ch == '-')
    			f = 0;
    	ret = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		ret = (ret << 1) + (ret << 3) + ch - '0';
    	return f ? ret : -ret;
    }
    
    int n;
    
    int s[MAXN];
    void modify(int x, int y) {
    	static int i;
    	for (i = x; i <= n; i += i & -i)
    		s[i] += y;
    }
    int query(int x) {
    	static int i, ret;
    	ret = 0;
    	for (i = x; i >= 1; i -= i & -i)
    		ret += s[i];
    	return ret;
    }
    
    struct SegTree {
    	int v;
    	SegTree *l, *r;
    } *root;
    void build(SegTree *&p, int l, int r) {
    	p = new SegTree();
    	p->v = 0;
    	p->l = p->r = NULL;
    	if (l == r)
    		return;
    	build(p->l, l, (l + r) >> 1);
    	build(p->r, ((l + r) >> 1) + 1, r);
    }
    void modify(SegTree *p, int l, int r, int x, int y) {
    	if (l == r) {
    		p->v = y;
    		return;
    	}
    	if (x <= (l + r) >> 1)
    		modify(p->l, l, (l + r) >> 1, x, y);
    	else
    		modify(p->r, ((l + r) >> 1) + 1, r, x, y);
    	p->v = std::max(p->l->v, p->r->v);
    }
    int query(SegTree *p, int l, int r, int x, int y) {
    	if (l == x && y == r)
    		return p->v;
    	if (y <= (l + r) >> 1)
    		return query(p->l, l, (l + r) >> 1, x, y);
    	else if (x > (l + r) >> 1)
    		return query(p->r, ((l + r) >> 1) + 1, r, x, y);
    	return std::max(query(p->l, l, (l + r) >> 1, x, (l + r) >> 1), query(p->r, ((l + r) >> 1) + 1, r, ((l + r) >> 1) + 1, y));
    }
    
    int main(/*int argc, char **argv*/) {
    	int i, j, mid, l, r, x[MAXN], a[MAXN], ans;
    	char v[MAXN];
    	
    	freopen("sequence.in", "r", stdin);
    	freopen("sequence.out", "w", stdout);
    	
    	n = getInt();
    	for (i = 1; i <= n; ++i)
    		x[i] = getInt();
    	memset(v, 0, sizeof v);
    	for (i = n; i >= 1; --i) {
    		l = 1;
    		r = n;
    		while (l <= r) {
    			mid = (l + r) >> 1;
    			j = mid - query(mid);
    			if (j == x[i] + 1) {
    				if (!v[mid]) {
    					v[a[i] = mid] = 1;
    					modify(mid, 1);
    					break;
    				} else
    					r = mid - 1;
    				continue;
    			}
    			if (j > x[i] + 1)
    				r = mid - 1;
    			else
    				l = mid + 1;
    		}
    	}
    	build(root, 1, n);
    	ans = 0;
    	for (i = 1; i <= n; ++i) {
    		j = query(root, 1, n, 1, a[i]);
    		modify(root, 1, n, a[i], j + 1);
    		if (ans < j + 1)
    			ans = j + 1;
    		printf("%d
    ", ans);
    	}
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

     第二题:仔细分析可以发现应该按照a + b递增的顺序贪心出井,然后dp,f[i][j]代表前i个逃离了j个的剩余最大高度。

    /* 
     * Problem: Dwarf
     * Author: Shun Yao
     */
    
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <assert.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <math.h>
    #include <time.h>
    
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #include <bitset>
    #include <utility>
    #include <iomanip>
    #include <numeric>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    //using namespace std;
    
    const int MAXN = 2222;
    
    int n, f[MAXN];
    
    struct Data {
    	int a, b;
    } c[MAXN];
    
    bool cmpa(Data a, Data b) {
    	return a.a + a.b < b.a + b.b;
    }
    
    int main(/*int argc, char **argv*/) {
    	int i, j, h;
    	
    	freopen("dwarf.in", "r", stdin);
    	freopen("dwarf.out", "w", stdout);
    	
    	scanf("%d", &n);
    	for (i = 1; i <= n; ++i)
    		scanf("%d%d", &c[i].a, &c[i].b);
    	scanf("%d", &h);
    	std::sort(c + 1, c + n + 1, cmpa);
    	for (i = 1; i <= n; ++i)
    		f[0] += c[i].a;
    	for (i = 1; i <= n; ++i)
    		f[i] = INT_MIN;
    	for (i = 1; i <= n; ++i)
    		for (j = i; j >= 1; --j)
    			if (f[j - 1] != INT_MIN && f[j - 1] + c[i].b >= h && f[j] < f[j - 1] - c[i].a)
    					f[j] = f[j - 1] - c[i].a;
    	for (i = n; i >= 0; --i)
    		if (f[i] >= 0)
    			break;
    	printf("%d", i);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    

     第三题:好吧,很明显二分图独立集(好像是好经典的题目啊!,据说匈牙利会被卡爆,我在BZOJ上交的。。。)

    /* 
     * Problem: TJOI2013-day2-Attack
     * Author: Shun Yao
     */
    
    #include <string.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <assert.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <math.h>
    #include <time.h>
    
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <queue>
    #include <deque>
    #include <string>
    #include <vector>
    #include <bitset>
    #include <utility>
    #include <iomanip>
    #include <numeric>
    #include <sstream>
    #include <iostream>
    #include <algorithm>
    #include <functional>
    
    //using namespace std;
    
    const int MAXN = 222;
    const int dx[8] = {1, 1, -1, -1, 2, 2, -2, -2};
    const int dy[8] = {2, -2, 2, -2, 1, -1, 1, -1};
    
    int n, mat[MAXN * MAXN];
    bool used[MAXN * MAXN];
    
    class Edge {
    public:
    	int v;
    	Edge *next;
    	Edge() {}
    	~Edge() {}
    	Edge(int V, Edge *ne) : v(V), next(ne) {}
    } *g[MAXN * MAXN];
    
    void add(int x, int y) {
    	g[x] = new Edge(y, g[x]);
    }
    
    bool find(int x) {
    	for (Edge *e = g[x]; e; e = e->next)
    		if (!used[e->v]) {
    			used[e->v] = 1;
    			if (!mat[e->v] || find(mat[e->v])) {
    				mat[e->v] = x;
    				return 1;
    			}
    		}
    	return 0;
    }
    
    int main(/*int argc, char **argv*/) {
    	int i, j, k, x, y, ans, sum;
    	char s[MAXN][MAXN];
    	
    	freopen("attack.in", "r", stdin);
    	freopen("attack.out", "w", stdout);
    	
    	scanf("%d", &n);
    	for (i = 1; i <= n; ++i)
    		scanf(" %s", s[i] + 1);
    	sum = 0;
    	for (i = 1; i <= n; ++i)
    		for (j = 1; j <= n; ++j) {
    			if (s[i][j] == '1')
    				continue;
    			++sum;
    			if ((i + j) & 1)
    				for (k = 0; k < 8; ++k) {
    					x = i + dx[k];
    					y = j + dy[k];
    					if (x < 1 || x > n || y < 1 || y > n || s[x][y] == '1')
    						continue;
    					add((i - 1) * n + j, (x - 1) * n + y);
    				}
    		}
    	ans = 0;
    	memset(mat, 0, sizeof mat);
    	for (i = 1; i <= n; ++i)
    		for (j = 1; j <= n; ++j)
    			if (s[i][j] == '0' && (i + j) & 1) {
    				memset(used, 0, sizeof used);
    				if (find((i - 1) * n + j))
    					++ans;
    			}
    	printf("%d
    ", sum - ans);
    	
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Java 实现 蓝桥杯 生兔子问题
    Java实现 蓝桥杯 基因牛的繁殖
    Java实现 蓝桥杯 基因牛的繁殖
    Java实现 蓝桥杯 基因牛的繁殖
    Java实现 LeetCode 33 搜索旋转排序数组
    Java实现 LeetCode 33 搜索旋转排序数组
    Java实现 LeetCode 33 搜索旋转排序数组
    深入探究VC —— 资源编译器rc.exe(3)
    深入探究VC —— 编译器cl.exe(2)
    深入探究VC —— 编译器cl.exe(1)
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3511050.html
Copyright © 2011-2022 走看看