Mokia(三维偏序)P4390

Posted ajmddzp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mokia(三维偏序)P4390相关的知识,希望对你有一定的参考价值。

提到cdq,就不得不提这道该死的,挨千刀的题目了。

极简题面:

给定一个二维平面,在ti时刻会在(xi,yi)放一个点,会在tj时刻查询一个方框里面的点的数量

看道题就是二维线段树乱搞啊,这么水???

数据范围劝退警告

单是一维都快有点吃不消了...1e6*1e6的数组?几个GB???

。。。

于是,伟大的CDQ分治出场了。

题面其实可以这样翻译:

按时插入点,询问小于(x,y)且时间也小于当前点的点的个数

这不就是CDQ的事吗?比模板题还要裸。。。

但是可能要差分一下(二维差分)因为统计的是点与00组成的大矩形,所以要剪去两个矩形,再加上一个小矩形,所以要统计四个点的偏序

总结一下,就是cdq。

第一维时间,第二维x,第三维y

一定要离线做

于是开始了愉快的CDQ

#include<bits/stdc++.h>
using namespace std;
const int maxn=505;

struct node

    int time,x,y,val,id;
e[maxn];
int m,cnt,t[maxn<<1],a[maxn],ans[maxn];
inline int lowbit(int x)

    return x & - x ;

void add(int x,int y)

    for(;x<=m;x+=lowbit(x))
    
        t[x]+=y;
    

int ask(int x)

    int res=0;
    for(;x;x-=lowbit(x))
    
        res+=t[x];
    
    return res;

bool cmp2(node a,node b)

    if(a.x!=b.x)return a.x<b.x;
    if(a.y!=b.y)return a.y<b.y;
    //else        return a.time<b.time;

bool cmp(node a,node b)

    return a.time<b.time;

void cdq(int l,int r)

    if(l==r)return;
    int mid=l+r>>1;
    cdq(l,mid);
    cdq(mid+1,r);
    sort(e+l,e+1+r,cmp2);
    for(int i=l;i<=r;i++)
    
        if(e[i].x<=mid&&e[i].id==0)
        add(e[i].y,e[i].val);
        else e[i].val+=ask(e[i].y);
    
    for(int i=l;i<=r;i++)
    
        if(e[i].x<=mid&&e[i].id==0)
        add(e[i].y,-e[i].val);
    

int read()

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

int main()

    read();
    m=read();
    int flag=read();
    while(flag!=3)
    
        if(flag==1)
        
            int x=read()+1,y=read()+1,val=read();
            e[++cnt]=(node)cnt,x,y,val,0;
        
        else
        
            int x1=read(),yl=read(),x2=read()+1,y2=read()+1;
            e[++cnt]=(node)cnt,x1,yl,0,1;//数据结构体化
            e[++cnt]=(node)cnt,x2,y2,0,1;
            e[++cnt]=(node)cnt,x2,yl,0,1;
            e[++cnt]=(node)cnt,x1,y2,0,1;
        
        flag=read();
    
    cdq(1,cnt);然后硬cdq就行了
    sort(e+1,e+cnt+1,cmp);
    for(int i=1;i<=cnt;++i)
    
        if(e[i].id==1)
        
            printf("%d\n",e[i].val+e[i+1].val-e[i+2].val-e[i+3].val);
            i+=3;
        
    
    return 0;

(完)

以上是关于Mokia(三维偏序)P4390的主要内容,如果未能解决你的问题,请参考以下文章

[bzoj] 1176 Mokia || CDQ分治

P4390 [BOI2007]Mokia 摩基亚(cdq分治)

P2433 - BZOJ 3262三维偏序陌上花开------三维偏序

cdq分治入门--BZOJ1176: [Balkan2007]Mokia

cdq分治解决三维偏序

三维偏序(陌上花开)