您的位置:首页 > 其它

洛谷3801:红色的幻想乡——题解

2018-05-26 21:34 197 查看

https://www.luogu.org/problemnew/show/P3801

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

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

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

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

我们将1操作改一下,改为先在x行放雾,后在y列放雾。

没错,这两个操作在一起就是1操作。

维护两棵线段树,记录当前有哪些行/列被覆盖过,则答案就是(在区间范围内的)行数*(y2-y1+1)+列数*(x2-x1+1)-行数*列数*2(也就是把它们相交的点抠掉啦)

(这题再次体现我的智商问题。)

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+5;
inline int read(){
int X=0,w=0;char ch=0;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
return w?-X:X;
}
int tr[N*4][2],n,m,q;
void mdy(int a,int l,int r,int k,int p){
if(l==r){
tr[a]

^=1; return; } int mid=(l+r)>>1; if(k<=mid)mdy(a<<1,l,mid,k,p); else mdy(a<<1|1,mid+1,r,k,p); tr[a][p]=tr[a<<1][p]+tr[a<<1|1][p]; } int qry(int a,int l,int r,int l1,int r1,int p){ if(r1<l||r<l1)return 0; if(l1<=l&&r<=r1)return tr[a][p]; int mid=(l+r)>>1; return qry(a<<1,l,mid,l1,r1,p)+qry(a<<1|1,mid+1,r,l1,r1,p); } int main(){ n=read(),m=read(),q=read(); for(int i=1;i<=q;i++){ int op=read(); if(op==1){ int x=read(),y=read(); mdy(1,1,n,x,0);mdy(1,1,m,y,1); }else{ int x1=read(),y1=read(),x2=read(),y2=read(); int ans1=qry(1,1,n,x1,x2,0); int ans2=qry(1,1,m,y1,y2,1); printf("%lld\n",(ll)ans1*(y2-y1+1)+(ll)ans2*(x2-x1+1)-(ll)2*ans1*ans2); } } return 0; }

[p]+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: