红色的幻想乡 洛谷p3801

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MrTinTin/article/details/83344750

题目背景

蕾米莉亚的红雾异变失败后,很不甘心。

题目描述

经过上次失败后,蕾米莉亚决定再次发动红雾异变,但为了防止被灵梦退治,她决定将红雾以奇怪的阵势释放。

我们将幻想乡看做是一个n*m的方格地区,一开始没有任何一个地区被红雾遮盖。蕾米莉亚每次站在某一个地区上,向东南西北四个方向各发出一条无限长的红雾,可以影响到整行/整列,但不会影响到她所站的那个地区。如果两阵红雾碰撞,则会因为密度过大而沉降消失。灵梦察觉到了这次异变,决定去解决它。但在解决之前,灵梦想要了解一片范围红雾的密度。可以简述为两种操作:

1 x y 蕾米莉亚站在坐标(x,y)的位置向四个方向释放无限长的红雾。

2 x1 y1 x2 y2 询问左上点为(x1,y1),右下点为(x2,y2)的矩形范围内,被红雾遮盖的地区的数量。

输入输出格式

输入格式:

第一行三个整数n,m,q,表示幻想乡大小为n*m,有q个询问。

接下来q行,每行3个或5个整数,用空格隔开,含义见题目描述。

输出格式:

对于每一个操作2,输出一行一个整数,表示对应询问的答案。

输入输出样例

输入样例#1: 复制

4 4 3
1 2 2
1 4 4
2 1 1 4 4

输出样例#1: 复制

8

说明

样例解释:

用o表示没有红雾,x表示有红雾,两次释放红雾后幻想乡地图如下:

oxox

xoxo

oxox

xoxo

数据范围:

对于20%的数据,1<=n,m,q<=200

对于 40%的数据,1<=n,m,q<=1000

对于100%的数据,1<=n,m,q<=100000

1<=x1,x2,x<=n x1<=x2

1<=y1,y2,y<=m y1<=y2

by-orangebird

放过的行数x×行长度+放过的列数y×列长度-抵消块数

记放过的行数x,放过的列数y,每行每列交叉1个,抵消块数就是2xy。

#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=100005;
int Tx[MAXN],x[MAXN],Ty[MAXN],y[MAXN];
int n,m,Q;
inline int Lowbit(int x)
{
	return x&(-x);
}
inline void add(int *a,int x,int n,int d)
{
	int i;
	for(i=x;i<=n;i+=Lowbit(i)){
		a[i]+=d;
	}
	return;
}
inline long long query(int *a,int x)
{
	int i;
	long long res=0;
	for(i=x;i;i-=Lowbit(i)){
		res+=a[i];
	}
	return res;
}
int main()
{
	ios::sync_with_stdio(false);
	int i,j,flag,x1,y1,x2,y2;
	cin>>n>>m>>Q;
	f(i,1,Q){
		cin>>flag;
		if(flag==1){
			cin>>x1>>y1;
			add(Tx,x1,n,x[x1]?-1:1);
			add(Ty,y1,m,y[y1]?-1:1);
			x[x1]^=1;
			y[y1]^=1;
		}
		else{
			cin>>x1>>y1>>x2>>y2;
			long long num1=query(Tx,x2)-query(Tx,x1-1);
			long long num2=query(Ty,y2)-query(Ty,y1-1);
			cout<<num1*(y2-y1+1)+num2*(x2-x1+1)-2*num1*num2<<endl;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/MrTinTin/article/details/83344750