首页 > 其他分享 >[CF983D]Arkady and Rectangles

[CF983D]Arkady and Rectangles

时间:2023-02-18 07:55:05浏览次数:43  
标签:Arkady ch 颜色 int 最大值 结点 Rectangles 统计 CF983D

\(\text{Solution}\)

二维平面很容易想到扫描线,然后不知道维护什么信息
颜色的变化自然要能记录下来,所以线段树每个结点维护一个 set 表示覆盖这个点代表区间的所有颜色
这样加入和删除就容易了

统计答案,无非是把当前能看到且未被统计过的颜色统计入答案
考虑一个颜色怎样合法,必然是存在一条从根到叶结点的路径使得这条路径上颜色的最大值是这个颜色
那么就维护当前能看到且未被统计过的颜色的最大值,取出最大值,标记为统计过,不断重复这样的过程,直到没有可以看到的颜色

最大值的维护要注意到是能看到的,一些统计过的且还在线段树上的颜色可能盖住别的颜色
具体来讲就是:子树传上来的能看到且未被统计过的颜色可能被当前结点的颜色(已统计过)覆盖导致不可见
或者当前结点的颜色(未被统计过)被子树已统计过的颜色覆盖导致不可见,所以要额外维护一个变量,具体见代码

\(\texttt{warning:}\) 线段的离散化直接离散化,不要先把边区间变成点的闭区间,不然会少掉一些必要的位置,如边区间 \(\text{[1,4],[1,2],[3,4]}\) 会错。
同理:点的闭区间离散化先变成左闭右开区间
不过影响因题而异,这题影响显著

\(\text{Code}\)

#include <bits/stdc++.h>
#define eb emplace_back
#define IN inline
using namespace std;

template <typename Tp>
IN void read(Tp &x) {
	x = 0; char ch = getchar(); int f = 0;
	for(; !isdigit(ch); f = (ch == '-' ? 1 : f), ch = getchar());
	for(; isdigit(ch); x = (x<<3)+(x<<1)+(ch^48), ch = getchar());
	if (f) x = ~x + 1;
}

const int N = 2e5 + 5;
int n, lsx[N], lsy[N], used[N];
struct Rect{int x0, y0, x1, y1;}a[N];
struct node{int id, v;};
vector<node> G[N];

struct SegmentTree {
	#define ls (p << 1)
	#define rs (ls | 1)
	#define mid (l + r >> 1)
	set<int> seg[N << 2]; int mx[N << 2], mn[N << 2];
	void pushup(int p, int fl) {
		if (fl) mx[p] = mn[p] = 0; else mx[p] = max(mx[ls], mx[rs]), mn[p] = min(mn[ls], mn[rs]);
		if (seg[p].size()) {
			int k = *(--seg[p].end());
			if (used[k]) mn[p] = max(mn[p], k); else mx[p] = max(mx[p], k);
		}
		mx[p] = (mn[p] > mx[p] ? 0 : mx[p]);
	}
	void update(int p, int l, int r, int x, int y, int z, int v) {
		if (x > r || y < l) return;
		if (x <= l && r <= y) {
			if (v == 1) seg[p].insert(z); else if (v == -1) seg[p].erase(z);
			return pushup(p, l == r), void();
		}
		update(ls, l, mid, x, y, z, v), update(rs, mid + 1, r, x, y, z, v), pushup(p, l == r);
	}
}T;

int main() {
	read(n); int totx = 0, toty = 0;
	for(int i = 1, x0, y0, x1, y1; i <= n; i++) {
		read(x0), read(y0), read(x1), read(y1), a[i] = Rect{x0, y0, x1, y1};
		lsx[++totx] = x0, lsx[++totx] = x1, lsy[++toty] = y0, lsy[++toty] = y1;
	}
	sort(lsx + 1, lsx + totx + 1), totx = unique(lsx + 1, lsx + totx + 1) - lsx - 1;
	sort(lsy + 1, lsy + toty + 1), toty = unique(lsy + 1, lsy + toty + 1) - lsy - 1;
	for(int i = 1, x0, x1, y0, y1; i <= n; i++) {
		x0 = lower_bound(lsx + 1, lsx + totx + 1, a[i].x0) - lsx;
		x1 = lower_bound(lsx + 1, lsx + totx + 1, a[i].x1) - lsx;
		y0 = lower_bound(lsy + 1, lsy + toty + 1, a[i].y0) - lsy;
		y1 = lower_bound(lsy + 1, lsy + toty + 1, a[i].y1) - lsy;
		a[i] = Rect{x0, y0, x1, y1}, G[x0].eb(node{i, 1}), G[x1].eb(node{i, -1});
	}
	int ans = 1;
	for(int i = 1; i <= totx; i++) {
		for(auto k : G[i]) T.update(1, 1, toty - 1, a[k.id].y0, a[k.id].y1 - 1, k.id, k.v);
		while (T.mx[1])
			++ans, used[T.mx[1]] = 1, T.update(1, 1, toty - 1, a[T.mx[1]].y0, a[T.mx[1]].y1 - 1, 0, 0);
	}
	printf("%d\n", ans);
}

标签:Arkady,ch,颜色,int,最大值,结点,Rectangles,统计,CF983D
From: https://www.cnblogs.com/leiyuanze/p/17131920.html

相关文章

  • 【题解】CF364E Empty Rectangles
    题目分析:如果题目放在序列上,也就是询问一个长度为\(n\)的序列有多少个子段满足其和为\(k\),那么考虑应该怎么做。显然就是使用分治,即左边的答案+右边的答案+跨过中间的......
  • Codeforces 1322 B. Count Subrectangles(贪心)
    题意:给出序列和序列矩阵是由和决定的问你可以从中截取多少个面积为显然可知的一个性质那就是当序列连续长度为,序列连续长度为,时这个部分序列形成的......
  • Codeforces 983 D Arkady and Rectangles 题解
    题目链接挺有意思的数据结构题,题面看着像个板子,其实还是有不少学问的。平面上一堆矩形的题目常见套路就是对\(x\)轴扫描线,\(y\)轴线段树维护,这题也不例外。我们先对坐标......
  • CF364E Empty Rectangles
    链接:https://www.luogu.com.cn/problem/CF364E题目描述:你有一个\(n*m\)的\(01\)矩阵,现在询问在这其中有多少个子矩阵满足包含\(k\)个\(1\),即和为\(k\)。题解:考虑枚举一个......
  • CF 1722E Counting Rectangles(前缀和)
    题目分析(摘自这篇博客,原博主关于包含的定义有错误,在此处做了修改)给出一个长度为1e5的矩阵序列和1e5次询问,每次询问给出两个上下界矩阵,保证大矩阵包含小矩阵,请输出矩阵序......
  • Hitachi2020E Odd Sum Rectangles
    Hitachi2020E看到\(\oplus\)操作和\(2^n-1\)时猜结论\(ans_{i,j}=\operatorname{popcount}(i\&j)\bmod2\),过不去,然后就不会了。然而令答案的二维前缀和为\(\opera......
  • Counting Rectangles(二维数组前缀和)
    题目链接题目描述:Youhave\(n\)rectangles,the\(i\)-threctanglehasheight\(h_i\)andwidth\(w_i\).Youareasked\(q\)queriesoftheform\(h_sw_sh_b......
  • [ARC070E] NarrowRectangles
    [ARC070E]NarrowRectangles首先考虑\(O(n^2)dp\),设\(dp_{i,j}\)表示前\(i\)个线段其右端点在\(j\)的最小代价,令\(len_i=R_i-L_i\)\[dp_{i,j}=|R_i-j|+Min_{k=j-len_i}......
  • [ARC081F] Flip and Rectangles
    考虑转换题目给出的条件。可以观察到一些性质若某个矩形能被操作为全\(1\),那么其任意子矩形也一定可以。任意行列交换不影响矩阵是否能变为全\(1\)然后重要的来了......
  • 【luogu CF1396D】Rainbow Rectangles(线段树)
    RainbowRectangles题目链接:luoguCF1396D题目大意给你一个L*L的矩形,里面有n个点,有各自的颜色。然后问你有多少个端点是整点的矩形可以圈出所有颜色至少有一个点。......