BZOJ 1176 [Balkan2007]Mokia ——CDQ分治

时间:2023-03-08 15:04:23
BZOJ 1176 [Balkan2007]Mokia ——CDQ分治

【题目分析】

同BZOJ2683,只需要提前处理s对结果的影响即可。

CDQ的思路还是很清晰的。

排序解决一维,

分治时间,

树状数组解决一维。

复杂度是两个log

【代码】

#include <cstdio>
#include <cstring>
#include <cstdlib>
//#include <cmath>

#include <set>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;

#define maxn 2000005

int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

struct data{
    int opt,id;
    int x,y,f,t;
}q[maxn],eq[maxn];

int ans[maxn],s;
int n,tot=0,cnt=0,opt,x1,y1,x2,y2,a;

struct Bit{
    int a[maxn];
    void init(){memset(a,0,sizeof a);}
    void add(int x,int f)
    {for (;x<=n;x+=x&(-x)) a[x]+=f;}
    int sum(int x)
    {
        int ret=0;
        for (;x;x-=x&(-x)) ret+=a[x];
        return ret;
    }
}t;

bool cmp(data a,data b)
{
    if (a.x==b.x&&a.y==b.y) return a.opt<b.opt;
    if (a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}

void solve(int l,int r)
{
    if (l==r) return ;
    int mid=(l+r)/2;
    for (int i=l;i<=r;++i)
    {
        if (q[i].t<=mid&&q[i].opt==1) t.add(q[i].y,q[i].f);
        if ( q[i].t>mid&&q[i].opt==2) ans[q[i].id]+=t.sum(q[i].y)*q[i].f;
    }
    for (int i=l;i<=r;++i)
        if (q[i].t<=mid&&q[i].opt==1) t.add(q[i].y,-q[i].f);
    int l1=l,l2=mid+1;
    for (int i=l;i<=r;++i) {if (q[i].t<=mid) eq[l1++]=q[i]; else eq[l2++]=q[i];}
    for (int i=l;i<=r;++i) q[i]=eq[i];
    solve(l,mid);
    solve(mid+1,r);
}

int main()
{
    s=read();n=read();
    while (scanf("%d",&opt)!=EOF&&opt!=3)
    {
        if (opt==1)
        {
            q[++cnt].opt=opt;
            q[cnt].x=read();
            q[cnt].y=read();
            q[cnt].f=read();
            q[cnt].t=cnt;
        }
        else
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2); ++tot;
            ans[tot]+=(x2-x1+1)*(y2-y1+1)*s;
            q[++cnt].opt=opt; q[cnt].x=x1-1; q[cnt].y=y1-1; q[cnt].f=1;  q[cnt].t=cnt; q[cnt].id=tot;
            q[++cnt].opt=opt; q[cnt].x=x1-1; q[cnt].y=y2;   q[cnt].f=-1; q[cnt].t=cnt; q[cnt].id=tot;
            q[++cnt].opt=opt; q[cnt].x=x2;   q[cnt].y=y1-1; q[cnt].f=-1; q[cnt].t=cnt; q[cnt].id=tot;
            q[++cnt].opt=opt; q[cnt].x=x2;   q[cnt].y=y2;   q[cnt].f=1;  q[cnt].t=cnt; q[cnt].id=tot;
        }
    }
    sort(q+1,q+cnt+1,cmp);
    solve(1,cnt);
    for (int i=1;i<=tot;++i) printf("%d\n",ans[i]);
}