zoukankan      html  css  js  c++  java
  • [BZOJ4548]小奇的糖果

    [BZOJ4548]小奇的糖果

    试题描述

    (N) 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的颜色。

    输入

    包含多组测试数据,第一行输入一个正整数 (T) 表示测试数据组数。

    接下来 (T) 组测试数据,对于每组测试数据,第一行输入两个正整数 (N)(K),分别表示点数和颜色数。

    接下来 (N) 行,每行描述一个点,前两个数 (x, y (|x|, |y| le 2^{30} - 1)) 描述点的位置,最后一个数 (z (1 le z ≤ k)) 描述点的颜色。

    输出

    对于每组数据在一行内输出一个非负整数 (ans),表示答案

    输入示例

    1
    10 3
    1 2 3
    2 1 1
    2 4 2
    3 5 3
    4 4 2
    5 1 2
    6 3 1
    6 7 1
    7 2 3
    9 4 2
    

    输出示例

    5
    

    数据规模及约定

    对于 (100\%) 的数据,(N le 100000,K le 100000,T le 3)

    题解

    此题和那道题是双倍经验关系。

    然而我那道题的做法在这里直接 T 飞了,所以再讲一个不那么慢的做法。(虽然也是基本垫底)

    如果给出的点没有提到所有颜色,就直接输出 (n)

    枚举不能包含的那个颜色 (c),令所有颜色为 (c) 的点的集和为 (S_c)。将 (S_c) 中的点按 (x) 坐标排序,然后我们从左到右依次考虑每个点,并以 (y) 坐标为关键字维护单调栈,当删除单调栈中的元素时统计一下极大子矩形的答案。询问矩形内部点数可以用主席树一个 (log n) 做。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
    #define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 100010
    #define maxnode 2000010
    #define pii pair <int, int>
    #define x first
    #define y second
    #define mp(x, y) make_pair(x, y)
    
    int n, K, nX[maxn], nY[maxn];
    pii ps[maxn];
    vector <pii > col[maxn];
    bool cmpy(pii a, pii b) { return a.y < b.y; }
    
    int ToT, rt[maxn], sumv[maxnode], lc[maxnode], rc[maxnode];
    void update(int& y, int x, int l, int r, int p) {
    	sumv[y = ++ToT] = sumv[x] + 1;
    	if(l == r) return ;
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) update(lc[y], lc[x], l, mid, p);
    	else update(rc[y], rc[x], mid + 1, r, p);
    	return ;
    }
    int query(int o, int l, int r, int ql, int qr) {
    	if(!o) return 0;
    	if(ql <= l && r <= qr) return sumv[o];
    	int mid = l + r >> 1, ans = 0;
    	if(ql <= mid) ans += query(lc[o], l, mid, ql, qr);
    	if(qr > mid) ans += query(rc[o], mid + 1, r, ql, qr);
    	return ans;
    }
    int Query(int xl, int xr, int yl, int yr) {
    	if(xl > xr || yl > yr) return 0;
    	return query(rt[yr], 1, n, xl, xr) - query(rt[yl-1], 1, n, xl, xr);
    }
    
    int S[maxn], top;
    void work() {
    	ToT = 0;
    	memset(rt, 0, sizeof(rt));
    	memset(lc, 0, sizeof(lc));
    	memset(rc, 0, sizeof(rc));
    	
    	n = read(); K = read();
    	rep(c, 1, K) col[c].clear();
    	rep(i, 1, n) {
    		int x = read(), y = read(), c = read();
    		nX[i] = x; nY[i] = y;
    		ps[i] = mp(x, y);
    		col[c].push_back(ps[i]);
    	}
    	sort(nX + 1, nX + n + 1);
    	sort(nY + 1, nY + n + 1);
    	rep(i, 1, n)
    		ps[i].x = lower_bound(nX + 1, nX + n + 1, ps[i].x) - nX,
    		ps[i].y = lower_bound(nY + 1, nY + n + 1, ps[i].y) - nY;
    	rep(c, 1, K) {
    		if(!col[c].size()) return (void)printf("%d
    ", n);
    		rep(i, 0, (int)col[c].size() - 1) {
    			pii& p = col[c][i];
    			p.x = lower_bound(nX + 1, nX + n + 1, p.x) - nX;
    			p.y = lower_bound(nY + 1, nY + n + 1, p.y) - nY;
    		}
    	}
    	sort(ps + 1, ps + n + 1, cmpy);
    	int j = 1;
    	rep(i, 1, n) {
    		rt[i] = rt[i-1];
    		while(j <= n && ps[j].y == i) update(rt[i], rt[i], 1, n, ps[j++].x);
    	}
    	int ans = 0;
    	rep(c, 1, K) {
    		sort(col[c].begin(), col[c].end());
    		// optimus
    		rep(i, 0, (int)col[c].size() - 1) ans = max(ans, Query(i ? col[c][i-1].x + 1 : 1, col[c][i].x - 1, 1, n));
    		ans = max(ans, Query(col[c][col[c].size()-1].x + 1, n, 1, n));
    		// down
    		rep(i, 0, (int)col[c].size() - 1) {
    			pii now = col[c][i];
    			while(top && col[c][S[top]].y > now.y) {
    				ans = max(ans, Query(top > 1 ? col[c][S[top-1]].x + 1 : 1, now.x - 1, 1, col[c][S[top]].y - 1));
    				top--;
    			}
    			S[++top] = i;
    		}
    		while(top) {
    			ans = max(ans, Query(top > 1 ? col[c][S[top-1]].x + 1 : 1, n, 1, col[c][S[top]].y - 1));
    			top--;
    		}
    		// up
    		rep(i, 0, (int)col[c].size() - 1) {
    			pii now = col[c][i];
    			while(top && col[c][S[top]].y < now.y) {
    				ans = max(ans, Query(top > 1 ? col[c][S[top-1]].x + 1 : 1, now.x - 1, col[c][S[top]].y + 1, n));
    				top--;
    			}
    			S[++top] = i;
    		}
    		while(top) {
    			ans = max(ans, Query(top > 1 ? col[c][S[top-1]].x + 1 : 1, n, col[c][S[top]].y + 1, n));
    			top--;
    		}
    	}
    	printf("%d
    ", ans);
    	return ;
    }
    
    int main() {
    	int T = read();
    	
    	while(T--) work();
    	
    	return 0;
    }
    
  • 相关阅读:
    linux下安装elasticsearch5.6.3
    linux下安装git
    环境安装备忘录 Zookeeper
    环境安装备忘录 JDK
    环境安装备忘录 Tomcat
    MySql 通过show status 优化数据库性能
    MySQL执行计划解读 转他人文章
    2015年12月21日 my.cnf 配置
    mysql 如何查看my.cnf的 位置
    mysql状态查看 QPS/TPS/缓存命中率查看
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/8479472.html
Copyright © 2011-2022 走看看