红色的幻想乡

题目背景

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

题目描述

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

我们将幻想乡看做是一个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

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=6e5+10;
int n,m,q;
void update(int rt,int po,int l,int r,ll *id){
    if(l==r){
        id[rt]^=1;
        return;
    }
    int mid=l+r>>1;
    if(po<=mid){
        update(rt<<1,po,l,mid,id);
    }
    else{
        update(rt<<1|1,po,mid+1,r,id);
    }
    id[rt]=id[rt<<1]+id[rt<<1|1];
}
ll query(int rt,int ql,int qr,int l,int r,ll *id){
    if(ql<=l&&qr>=r){
        return id[rt];
    }
    int mid=l+r>>1;
    ll sum=0;
    if(ql<=mid){
        sum+=query(rt<<1,ql,qr,l,mid,id);
    }
    if(qr>mid){
        sum+=query(rt<<1|1,ql,qr,mid+1,r,id);
    }
    return sum;
}
ll s[maxn],t[maxn];
int main() {
    scanf("%d%d%d",&n,&m,&q);
    ll x1,y1,x2,y2;
    for(register int i=1,op;i<=q;++i){
            scanf("%d",&op);
            if(op==1){
                scanf("%lld%lld",&x1,&y1);
                update(1,x1,1,n,s);
                update(1,y1,1,m,t);
            }
            else{
                scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
                ll l=query(1,x1,x2,1,n,s);
                ll r=query(1,y1,y2,1,m,t);
                printf("%lld
",l*(y2-y1+1)+r*(x2-x1+1)-l*r*2);
            }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/czy-power/p/11392726.html