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的主要内容,如果未能解决你的问题,请参考以下文章
P4390 [BOI2007]Mokia 摩基亚(cdq分治)
P2433 - BZOJ 3262三维偏序陌上花开------三维偏序