红色的幻想乡题解
作者:互联网
题目传送门:https://www.luogu.com.cn/problem/P3801
由于数据范围是1e5 so 二维树状数组一定挂 因此我们想到降维即用一维树状数组,那我们该如何构造数组由于本题涉及行和列的关系我们不妨构造两个一维树状数组lin[], row[],row[]记录前i行有多少行有迷雾,lin[]记录前i列有多少列有迷雾。但有的地方可能被多次施法所以我们还需要两个数组来标记行列的状态(是否有迷雾)红雾的数量可以用容斥原理求得。计算方式为:放过的行数×行长度++放过的列数\times×列长度-−重复计算的个数(即行数 * 列数 * 2)
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 10; int lin[maxn], row[maxn]; bool li[maxn], ro[maxn];//记录是否有红雾 1 有 0 无 int n, m, q; int lowbit(int x){ return x & -x; } void update(int c[], int id, int x, int pos){ for(int i = id; i <= pos; i += lowbit(i)) c[i] += x; } int getsum(int c[], int id){ int sum = 0; for(int i = id; i; i -= lowbit(i)) sum += c[i]; return sum; }//树状数组基本操作 int main(){ scanf("%d%d%d", &n, &m, &q); for(int i = 1; i <= q; i++){ int k, x1, y1; scanf("%d%d%d", &k, &x1, &y1); if(k == 1){ if(!li[x1]) update(lin, x1, 1, n);//无红雾加一 else update(lin, x1, -1, n);//有红雾减一 li[x1] ^= 1;// 更新x1的状态 (a ^ a = 0, 0 ^ a = a) if(!ro[y1]) update(row, y1, 1, m); else update(row, y1, -1, m); ro[y1] ^= 1; 同上 } else{ int x2, y2; scanf("%d%d", &x2, &y2); int s1 = getsum(lin, x2) - getsum(lin, x1 - 1),//计算行数 s2 = getsum(row, y2) - getsum(row, y1 - 1);//计算列数 printf("%lld\n",1ll * (y2 - y1 + 1) * s1 + 1ll * (x2 - x1 + 1) * s2 - 1ll * s2 * s1 * 2);//计算红雾个数 } } return 0; }
标签:幻想,红色,树状,int,题解,lin,maxn,数组,row 来源: https://www.cnblogs.com/lyclly/p/16541981.html