luogu P3801 红色的幻想乡

嘟嘟嘟

首先人人都能想到是线段树,不过二维线段树肯定会MLE+TLE的。

我们换一种想法,不去修改整个区间,而是修改一个点:开横竖两个线段树,分别记录哪些行和列被修改了。因为如果两阵红雾碰撞,则会因为密度过大而沉降消失,所以自然想到亦或。

统计的时候求出这个矩形内有哪些行和列被修改了,接着把这些行和列的长度累加到答案中,但这样的话交点处不仅会重加,而实际上应该是0,所以在减去两倍的被修改的行,列数。

综上:单点亦或修改,区间查询。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 1e5 + 5;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) {last = ch; ch = getchar();}
26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 {
32     if(x < 0) x = -x, putchar('-');
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36 
37 int n, m, q;
38 struct Tree
39 {
40     int l[maxn << 2], r[maxn << 2], sum[maxn << 2];
41     Tree()
42     {
43         Mem(l, 0); Mem(r, 0);
44         Mem(sum, 0);
45     }
46     void build(int L, int R, int now)
47     {
48         l[now] = L; r[now] = R;
49         if(L == R) return;
50         int mid = (L + R) >> 1;
51         build(L, mid, now << 1);
52         build(mid + 1, R, now << 1 | 1);
53     }
54     void update(int idx, int now)
55     {
56         if(l[now] == r[now]) {sum[now] ^= 1; return;}
57         int mid = (l[now] + r[now]) >> 1;
58         if(idx <= mid) update(idx, now << 1);
59         else update(idx, now << 1 | 1);
60         sum[now] = sum[now << 1] + sum[now << 1 | 1];
61     }
62     int query(int L, int R, int now)
63     {
64         if(L == l[now] && R == r[now]) return sum[now];
65         int mid = (l[now] + r[now]) >> 1;
66         if(R <= mid) return query(L, R, now << 1);
67         else if(L > mid) return query(L, R, now << 1 | 1);
68         else return query(L, mid, now << 1) + query(mid + 1, R, now << 1 | 1);
69     }
70 }X, Y;
71 
72 int main()
73 {
74     n = read(); m = read(); q = read();
75     X.build(1, n, 1); Y.build(1, m, 1);
76     for(int i = 1; i <= q; ++i)
77     {
78         int d = read();
79         if(d == 1)
80         {
81             int x = read(), y = read();
82             X.update(x, 1); Y.update(y, 1);
83         }
84         else
85         {
86             int xa = read(), ya = read(), xb = read(), yb = read();
87             int a = X.query(xa, xb, 1), b = Y.query(ya, yb, 1);
88             write((ll)a * (ll)(yb - ya + 1) + (ll)b * (ll)(xb - xa + 1) - (ll)a * b * 2);
89             enter;
90         }
91     }
92     return 0;
93 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9714432.html