zoukankan      html  css  js  c++  java
  • Bzoj4548 小奇的糖果(链表+树状数组)

    题面

    Bzoj

    题解

    很显然,我们只需要考虑单独取线段上方的情况,对于下方的把坐标取反再做一遍即可(因为我们只关心最终的答案)

    建立树状数组维护一个横坐标区间内有多少个点,维护双向链表实现查询一个点左(右)横坐标最大(小)的与它相同的点。

    首先枚举没有取到的颜色,找出所有不包含这种颜色的区间,更新答案。

    接着考虑两个相同颜色的点的贡献,按照纵坐标从大到小枚举所有的点,分别在树状数组和双向链表中删除当前点,并利用这个点左右两边和它颜色相同的点之间的区间内点的个数更新答案。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::min; using std::max;
    using std::sort; using std::swap;
    using std::unique; using std::lower_bound;
    typedef long long ll;
    
    template<typename T>
    void read(T &x) {
        int flag = 1; x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
        while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
    }
    
    const int N = 1e5 + 10;
    int T, n, K, x[N], ans;
    struct data { int x, y, z, id; } p[N];
    int disc[N], t[N];//树状数组
    int last[N], l[N], r[N];//双向链表
    
    void add (int x, int y) { while(x <= n + 1) t[x] += y, x += (x & -x); }
    int query (int x) { int y = 0; while(x) y += t[x], x -= (x & -x); return y; }
    inline bool cmpx(const data &a, const data &b) { return a.x < b.x; }
    inline bool cmpy(const data &a, const data &b) { return a.y < b.y; }
    void update(int l, int r) {
    	if(l > r) return ;
    	int tmp = query(r) - query(l - 1);
    	ans = max(tmp, ans);
    }
    
    void doit () {
    	x[0] = 0, x[n + 1] = n + 1;
    	memset(last, 0, sizeof last), memset(t, 0, sizeof t);
    	sort(&p[1], &p[n + 1], cmpx);
    	for(int i = 1; i <= n; ++i) add(p[i].x, 1);
    	for(int i = 1; i <= n; ++i) {
    		int t = p[i].id, L= last[p[i].z];
    		l[t] = L, r[t] = n + 1;
    		if(L) r[L] = t;
    		update(x[L] + 1, x[t] - 1);
    		last[p[i].z] = t;
    	}
    	for(int i = 1; i <= K; ++i)
    		update(x[last[i]] + 1, n + 1);
    	sort(&p[1], &p[n + 1], cmpy);
    	for(int i = 1, j = 1; i <= n; ++i) {
    		int t = p[i].id;
    		while(j <= n && p[j].y == p[i].y) add(p[j].x, - 1), ++j;
    		l[r[t]] = l[t], r[l[t]] = r[t];
    		update(x[l[t]] + 1, x[r[t]] - 1);
    	}
    }
    
    int main () {
    	read(T);
    	while(T--) {
    		ans = 0, read(n), read(K); int m = n;
    		for(int i = 1; i <= n; ++i)
    			read(p[i].x), read(p[i].y), read(p[i].z), p[i].id = i;
    		for(int i = 1; i <= n; ++i)
    			disc[i] = p[i].x;
    		sort(&disc[1], &disc[m + 1]), m = unique(&disc[1], &disc[m + 1]) - disc - 1;
    		for(int i = 1; i <= n; ++i) {
    			p[i].x = lower_bound(&disc[1], &disc[m + 1], p[i].x) - disc;
    			x[i] = p[i].x;
    		}
    		doit(); for(int i = 1; i <= n; ++i) p[i].y = -p[i].y; doit();
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    POJ数据结构专辑(含部分题解)
    第K小数 uva 10041 Vito's Family poj 2388 Who's in the Middle
    POJ 1195 Mobile phones (二维树状树组)
    python 学习体会
    ACM竞赛常用STL(二)之STLalgorithm
    计算机科学中的树
    ctf古典密码从0到
    漏洞挖掘的艺术面向源码的静态漏洞挖掘
    漏洞挖掘的艺术面向二进制的静态漏洞挖掘
    实战演示 H5 性能分析
  • 原文地址:https://www.cnblogs.com/water-mi/p/10350663.html
Copyright © 2011-2022 走看看