P3801 红色的幻想乡
Posted garen-wang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3801 红色的幻想乡相关的知识,希望对你有一定的参考价值。
基本的线段树和容斥原理
我好菜啊!
题目中其实有一点拐了弯:她把两团雾气中和沉降和在原地放置两种情况分开了。
但你只要画个图就能发现:在都有标记的行和列上,一旦有交叉,这个点就是没雾气的。
在一个点放置雾气,相当于在一行和一列都放了雾气。
一个区域内的雾气,相当于所有有标记的行和列占的总面积再减掉那些沉降掉的。
不难发现:当在行中放了(x)个雾气,在列中放了(y)个雾气时,被中和掉的就有(xy)个。
其实也不难算的,手膜一下就知道了。
代码:
#include<cstdio>
const int maxn = 100005;
struct segTree
{
int sum[maxn << 2];
#define lson (root << 1)
#define rson (root << 1 | 1)
void pushup(int root)
{
sum[root] = sum[lson] + sum[rson];
}
void update(int root, int l, int r, int p)
{
if(l == r) sum[root] ^= 1;
else
{
int mid = (l + r) >> 1;
if(p <= mid) update(lson, l, mid, p);
else update(rson, mid + 1, r, p);
pushup(root);
}
}
int query(int root, int l, int r, int x, int y)
{
if(r < x || y < l) return 0;
if(x <= l && r <= y) return sum[root];
int mid = (l + r) >> 1;
return query(lson, l, mid, x, y) + query(rson, mid + 1, r, x, y);
}
#undef lson
#undef rson
} seg1, seg2;
int n, m, q;
int read()
{
int ans = 0, s = 1;
char ch = getchar();
while(ch > ‘9‘ || ch < ‘0‘){ if(ch == ‘-‘) s = -1; ch = getchar(); }
while(ch >= ‘0‘ && ch <= ‘9‘) ans = ans * 10 + ch - ‘0‘, ch = getchar();
return s * ans;
}
int main()
{
n = read(), m = read(), q = read();
while(q--)
{
int opt = read();
if(opt == 1)
{
int x = read(), y = read();
seg1.update(1, 1, n, x);
seg2.update(1, 1, n, y);
}
else if(opt == 2)
{
int x = read(), y = read(), xx = read(), yy = read();
int res1 = seg1.query(1, 1, n, x, xx);
int res2 = seg2.query(1, 1, n, y, yy);
printf("%lld
", 1ll * res1 * (yy - y + 1) + 1ll * res2 * (xx - x + 1) - 2 * res1 * res2);
}
}
return 0;
}
以上是关于P3801 红色的幻想乡的主要内容,如果未能解决你的问题,请参考以下文章