• 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;
    }
    
  • 相关阅读:
    newCachedThreadPool无上限线程池使用
    newFixedThreadPool固定线程使用
    java定时器
    http文件上传/下载
    ThreadPoolExecutor线程池
    阻塞队列
    非阻塞队列
    IO文件夹拷贝(文件内含有文件和文件夹)
    MD5加密
    web.xml文件的作用
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3511050.html
Copyright © 2020-2023  润新知