您的位置:首页 > 其它

【JZOJ3893】【NOIP2014模拟10.25A组】画矩形

2017-01-21 08:00 357 查看

Description



Data Constraint



Solution

后来听说这是一道CDQ分治的题目。

对于一个矩形,我们可以在它的左的左下角和右上角打一个+1标记,左上角和右下角打一个-1标记。那么对于一个点的询问就成了询问它左下角的和为多少。我们可以把所有插入拆成两个左边和右边的对一列的操作,和询问放在一起按横坐标进行排序。然后二分时间,对于每次二分的时间t,我们把区间内时间<=t的插入放入树状数组内统计,然后计算区间内时间>=t的方案,然后再把区间内时间

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=4e5+5;
struct code{
int a,l,r,t,bz;
}a[maxn],b[maxn];
int f[maxn],ans1[maxn];
int n,i,t,j,k,l,num,x,y,z,ans,num1;
bool cmp(code x,code y){
return x.a<y.a || x.a==y.a && x.bz<y.bz;
}
int lowbit(int x){
return x&(-x);
}
void insert(int x,int z){
if (x>maxn-5) return;
f[x]+=z;insert(x+lowbit(x),z);
}
int find(int x){
if (x<1) return 0;
return f[x]+find(x-lowbit(x));
}
void dg(int l,int r){
int mid,i,j,t;
if (l==r) return;
mid=(l+r)/2;
for (i=l;i<=r;i++){
if (a[i].t<=mid && a[i].bz!=1){
if (a[i].bz==0) insert(a[i].l,1),insert(a[i].r+1,-1);
else insert(a[i].l,-1),insert(a[i].r+1,1);
}else if (a[i].bz==1 && a[i].t>=mid) ans1[a[i].r]+=find(a[i].l);
}
for (i=l;i<=r;i++)
if (a[i].t<=mid && a[i].bz!=1){
if (a[i].bz==0) insert(a[i].l,-1),insert(a[i].r+1,+1);
else insert(a[i].l,+1),insert(a[i].r+1,-1);
}
num=l-1;
if (r-l==1) return;
for (i=l;i<=r;i++)
if (a[i].t<mid) b[++num]=a[i];
num++;
for (i=l;i<=r;i++)
if (a[i].t>mid) b[++num]=a[i];
for (i=l;i<=r;i++)
a[i]=b[i];
dg(l,mid-1);
dg(mid+1,r);
}
int main(){
//  freopen("data.in","r",stdin);freopen("data.out","w",stdout);
scanf("%d",&n);
for (i=1;i<=n;i++){
scanf("%d%d%d",&z,&x,&y);x++;y++;
if (z) a[++num].a=x,a[num].l=y,a[num].t=num,a[num].bz=1,a[num].r=++num1;
else{
a[++num].t=num,a[++num].t=num;a[num-1].a=x;scanf("%d%d",&a[num].a,&a[num].r);
a[num].a++;a[num].r++;a[num-1].l=a[num].l=y;a[num-1].r=a[num].r;
a[num-1].bz=0,a[num].bz=2;
}
}
sort(a+1,a+num+1,cmp);
dg(1,num);
for (i=1;i<=num1;i++)
printf("%d\n",ans1[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: