40pts求助(内附有注释及思路
查看原帖
40pts求助(内附有注释及思路
490978
小超手123楼主2023/12/20 08:52

单独用扫描线计算竖线与横线的并(部分1),并暴力容斥斜线与斜线的并(部分2),再减掉两个部分的交集的部分。

其中部分1的计算我是复制的扫描线的板子,应该没什么问题,试过有95分的。

感觉是部分2的计算:或者计算两个部分的交集的交集有问题,麻烦大佬帮忙看看。

部分2的计算:

void dfs(int k) { //容斥计算斜线本身的并 
	if(k > hh) {
		int z = -1;
		int len = 0;
		int LL = 0, RR = 1e18;
        for(int i = 1; i <= hh; i++) {
        	if(now[i] == 0) continue;
        	len++;
            int u = R[i].Y1 - R[i].X1;
            if(z == -1) {
            	z = u;
			}
			else if(z != u) {
				return;
			}
			LL = max(LL, R[i].X1);
			RR = min(RR, R[i].X2);
		}
		if(LL > RR || LL == 0 && RR == 1e18) return;
		if(len % 2 == 1) ans += (RR - LL + 1);
		else ans -= (RR - LL + 1);
		return;
	}
	now[k] = 1;
	dfs(k + 1);
	now[k] = 0;
	dfs(k + 1);
}

交集的计算:

for(int i = 1; i <= hh; i++) {
    	for(int j = 1; j <= nn; j++) { //暴力计算两不分的并 
    		int b = R[i].Y1 - R[i].X1;
    		if(Y1[j] == Y2[j]) {
    		    int xx = Y1[j] - b;
    		    if(X1[j] <= xx && xx <= X2[j]) {
    		    	if(P[xx][Y1[j]] == 0) {
    		    		P[xx][Y1[j]] = 1;
    		    		ans--;
					}
				}
			}
			else if(X1[j] == X2[j]) {
				int yy = X1[j] + b;
				if(Y1[j] <= yy && yy <= Y2[j]) {
					if(P[X1[j]][yy] == 0) {
						P[X1[j]][yy] = 1;
						ans--;
					}
				}
			}
		}
	}

总代码:

#include<bits/stdc++.h>
#define int long long
#define N 500005
using namespace std;
int read() {
	int x = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
	return x * f;
}
void write(int x) {
	if(x < 0) putchar('-'), x = -x;
	if(x > 9) write(x / 10);
	putchar('0' + x % 10);
}
int n, m, q, ans, c;
int X1[N], Y1[N], X2[N], Y2[N]; 
int xx1[N], yy1[N], xx2[N], yy2[N];
int b1[N], cnt1, d1[N], len1;
int b2[N], cnt2, d2[N], len2; 
struct Tree{
    int Min[N * 4], c[N * 4], tag[N * 4]; //维护区间最小值以及区间最小值的个数 
    void pushup(int u) {
    	if(Min[u * 2] == Min[u * 2 + 1]) {
    		Min[u] = Min[u * 2];
    	    c[u] = c[u * 2] + c[u * 2 + 1];
		}
        else if(Min[u * 2] < Min[u * 2 + 1]) {
        	Min[u] = Min[u * 2];
        	c[u] = c[u * 2];
		}
		else {
			Min[u] = Min[u * 2 + 1];
        	c[u] = c[u * 2 + 1];
		}
    }
    void maketag(int u, int L, int R, int x) {
        Min[u] += x;
        tag[u] += x;
    }
    void pushdown(int u, int L, int R) {
        int mid = (L + R) / 2;
        maketag(u * 2, L, mid, tag[u]);
        maketag(u * 2 + 1, mid + 1, R, tag[u]);
        tag[u] = 0;
    }
    void build(int u, int L, int R) {
    	tag[u] = 0;
    	if(L == R) {
    		Min[u] = 0;
    		c[u] = d1[R + 1] - d1[L];
    		return;
		}
		int mid = (L + R) / 2;
		build(u * 2, L, mid);
		build(u * 2 + 1, mid + 1, R);
		pushup(u);
	}
    void update(int u, int L, int R, int l, int r, int x) {
        if(R < l || r < L) return;
        if(l <= L && R <= r) {
            maketag(u, L, R, x * (d1[R + 1] - d1[L]));
            return;
        }
        int mid = (L + R) / 2;
        pushdown(u, L, R);
        update(u * 2, L, mid, l, r, x);
        update(u * 2 + 1, mid + 1, R, l, r, x);
        pushup(u);
    }
    int query(int u, int L, int R, int l, int r) {
        if(R < l || r < L) return 0;
        if(l <= L && R <= r) {
        	if(Min[u] != 0) return d1[R + 1] - d1[L];
        	else return d1[R + 1] - d1[L] - c[u];
		}
        int mid = (L + R) / 2;
        pushdown(u, L, R);
        return query(u * 2, L, mid, l, r), query(u * 2 + 1, mid + 1, R, l, r);
    }
}t;
struct node{
	int opt, L, R;
};
vector<node>Q[N];
struct End{
	int X1, Y1, X2, Y2;
}R[N];
int hh = 0;
unordered_map<int, unordered_map<int, int>>P;
bool now[N];
void dfs(int k) { //容斥计算斜线本身的并 
	if(k > hh) {
		int z = -1;
		int len = 0;
		int LL = 0, RR = 1e18;
        for(int i = 1; i <= hh; i++) {
        	if(now[i] == 0) continue;
        	len++;
            int u = R[i].Y1 - R[i].X1;
            if(z == -1) {
            	z = u;
			}
			else if(z != u) {
				return;
			}
			LL = max(LL, R[i].X1);
			RR = min(RR, R[i].X2);
		}
		if(LL > RR || LL == 0 && RR == 1e18) return;
		if(len % 2 == 1) ans += (RR - LL + 1);
		else ans -= (RR - LL + 1);
		return;
	}
	now[k] = 1;
	dfs(k + 1);
	now[k] = 0;
	dfs(k + 1);
}
signed main() {
    c = read();
	n = read(); m = read(); q = read();
	int nn = 0;
    for(int i = 1; i <= q; i++) {
        int opt = read();
        if(opt <= 2) {
        	nn++; 
        	X1[nn] = read(); Y1[nn] = read();
    	    X2[nn] = read() + 1; Y2[nn] = read() + 1;
        	b1[++cnt1] = Y1[nn]; b2[++cnt2] = X1[nn];
    	    b1[++cnt1] = Y2[nn]; b2[++cnt2] = X2[nn];
		}
    	else {
    		hh++;
    		R[hh].X1 = read(); R[hh].Y1 = read();
    		R[hh].X2 = read(); R[hh].Y2 = read();
		}
	} //b1存y,b2存x 
	dfs(1);
	sort(b1 + 1, b1 + cnt1 + 1);
	sort(b2 + 1, b2 + cnt2 + 1);
	for(int i = 1; i <= cnt1; i++) 
		if(i == 1 || b1[i] != b1[i - 1]) d1[++len1] = b1[i];
	for(int i = 1; i <= cnt2; i++) 
		if(i == 1 || b2[i] != b2[i - 1]) d2[++len2] = b2[i];
	for(int i = 1; i <= nn; i++) {
		xx1[i] = lower_bound(d2 + 1, d2 + len2 + 1, X1[i]) - d2;
		yy1[i] = lower_bound(d1 + 1, d1 + len1 + 1, Y1[i]) - d1;
		xx2[i] = lower_bound(d2 + 1, d2 + len2 + 1, X2[i]) - d2;
		yy2[i] = lower_bound(d1 + 1, d1 + len1 + 1, Y2[i]) - d1;
		Q[xx1[i]].push_back((node){1, yy1[i], yy2[i]});
		Q[xx2[i]].push_back((node){-1, yy1[i], yy2[i]});
	}
	t.build(1, 1, len1 - 1);
	for(int i = 1; i <= len2 - 1; i++) {
		for(int k = 0; k < Q[i].size(); k++) {
			node cmp = Q[i][k];
			t.update(1, 1, len1 - 1, cmp.L, cmp.R - 1, cmp.opt);
		}
		ans += (d2[i + 1] - d2[i]) * t.query(1, 1, len1 - 1, 1, len1 - 1);
	} //扫描线计算横线和竖线本身的并 
    for(int i = 1; i <= nn; i++) X2[i]--, Y2[i]--;
    for(int i = 1; i <= hh; i++) {
    	for(int j = 1; j <= nn; j++) { //暴力计算两不分的并 
    		int b = R[i].Y1 - R[i].X1;
    		if(Y1[j] == Y2[j]) {
    		    int xx = Y1[j] - b;
    		    if(X1[j] <= xx && xx <= X2[j]) {
    		    	if(P[xx][Y1[j]] == 0) {
    		    		P[xx][Y1[j]] = 1;
    		    		ans--;
					}
				}
			}
			else if(X1[j] == X2[j]) {
				int yy = X1[j] + b;
				if(Y1[j] <= yy && yy <= Y2[j]) {
					if(P[X1[j]][yy] == 0) {
						P[X1[j]][yy] = 1;
						ans--;
					}
				}
			}
		}
	}
	write(ans);
	return 0;
}
/*
0
5 5 3
1 1 3 5 3
2 3 1 3 5
3 1 1 5 5
*/
2023/12/20 08:52
加载中...