第十一届蓝桥杯国赛C\C++A组 奇偶覆盖

第十一届蓝桥杯国赛C\C++A组 奇偶覆盖_第1张图片
本题就是一个扫描线的模板题,但是需要改一下线段树的中存储的信息,每个结点需要存储一下当前结点下多少长度是被奇(或偶数)个矩形覆盖的即可。
并且本题的坐标范围很大,但是个数很少,所以可以离散化一下再做。
本代码应该无任何问题了,如果有佬发现有问题请及时私聊我更改哦~

#include 
#define IO (ios::sync_with_stdio(false), cin.tie(0), cout.tie(0))
#define INF 0x3f3f3f3f
#define ll long long
#define pii pair
#define pll pair
#define vs vector
#define pk push_back
#define vss vector >
#define sz(x) (int)(x).size()
#define mk(a, b) make_pair(a, b)
#define Max(a, b) (a > b ? a : b)
#define Min(a, b) (a < b ? a : b)
#define Swap(a, b) (a ^= b, b ^= a, a ^= b)
#define rep(a, b, c) for(register int a = b; a <= c; ++ a)
#define per(a, b, c) for(register int a = b; a >= c; -- a)
using namespace std;

const int N = 1e5 + 5;

int n, m, T;
int alls[N << 2];

struct Segment
{
     
	int x, y1, y2;
	int k;
	bool operator< (const Segment &q) const {
     
		return x < q.x;
	}
} seg[N << 2];

struct Node 
{
     
	int l, r;
	int cnt;
	int len1, len2;
}tr[N << 4];

template<class T>
inline void read(T &x)
{
     
	x = 0; T f = 1; char c = getchar();
	while(c < '0' || c > '9') {
      if(c == '-') f = -1; c = getchar(); }
	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
	x *= f; 
}

template<class T>
inline void write(T x)
{
     
    if(x < 0) putchar('-'), x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

int get(double x)
{
     
	return lower_bound(alls, alls + m, x) - alls;
}

void build(int u, int l, int r)
{
     
	tr[u] = {
     l, r};
	if(l >= r) return;
	int mid = l + r >> 1;
	build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r);
}

void pushup(int u)
{
     
	if(tr[u].cnt)
	{
     
		if(tr[u].cnt & 1)
		{
     
			tr[u].len1 = tr[u << 1].len2 + tr[u << 1 | 1].len2;
			tr[u].len2 = tr[u << 1].len1 + tr[u << 1 | 1].len1;
			tr[u].len1 += alls[tr[u].r + 1] - alls[tr[u].l] - tr[u].len1 - tr[u].len2;
		}
		else
		{
     
			tr[u].len2 = tr[u << 1].len2 + tr[u << 1 | 1].len2;
			tr[u].len1 = tr[u << 1].len1 + tr[u << 1 | 1].len1;
			tr[u].len2 += alls[tr[u].r + 1] - alls[tr[u].l] - tr[u].len1 - tr[u].len2;
		}
	}
	else if(tr[u].l != tr[u].r)
	{
     
		tr[u].len1 = tr[u << 1].len1 + tr[u << 1 | 1].len1;
		tr[u].len2 = tr[u << 1].len2 + tr[u << 1 | 1].len2;
	}
	else tr[u].len1 = tr[u].len2 = 0;
}

void modify(int u, int l, int r, int k)
{
     
	if(tr[u].l >= l && tr[u].r <= r)
	{
     
		tr[u].cnt += k;
		pushup(u);
		return;
	}
	
	int mid = tr[u].l + tr[u].r >> 1;
	if(l <= mid) modify(u << 1, l, r, k);
	if(r > mid) modify(u << 1 | 1, l, r, k);
	pushup(u);
}

int main()
{
     
	
	scanf("%d", &n);
	
	m = 0;
	for(int i = 0; i < n; i ++ )
	{
     
		int x1, y1, x2, y2;
		scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
		alls[m] = y1; seg[m ++ ] = {
     x1, y1, y2, 1};
		alls[m] = y2; seg[m ++ ] = {
     x2, y1, y2, -1};
	}
	
	sort(seg, seg + m);
	
	sort(alls, alls + m);
	m = unique(alls, alls + m) - alls;
	
	build(1, 0, m - 2);
	
	ll res1 = 0, res2 = 0;
	for(int i = 0; i < n << 1; i ++ )
	{
     
		if(i)
		{
     
			res1 += tr[1].len1 * 1ll * (seg[i].x - seg[i - 1].x);
			res2 += tr[1].len2 * 1ll * (seg[i].x - seg[i - 1].x);
		}
		modify(1, get(seg[i].y1), get(seg[i].y2) - 1, seg[i].k);
	}
	
	printf("%lld\n%lld\n", res1, res2);

	return 0;
}

你可能感兴趣的:(蓝桥杯国赛题解,算法)