【NOIP2014模拟10.25A组】画矩形

来源:互联网 发布:安卓6.0读取数据库 编辑:程序博客网 时间:2024/06/07 06:59

题目

这里写图片描述

分析

由于要求按时间顺序来操作,考虑整体二分:
对于一段二分出来的区间,将左区间的修改和右区间的查询取出来,每次更新每个查询的答案,正确性显然。
现在有一对修改和查询的操作(保证所有的查询都在修改之后),按x坐标排序,将矩形拆成左右两条线,用扫描线,树状数组维护,更新答案。

#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>const int maxlongint=2147483647;const int mo=1000000007;const int N=200005;using namespace std;struct ddx{    int be,k,x,x1,y1,v;}d[N];int n,re[N][8],ans[N],sum[N+N],tot;bool cmp(ddx x,ddx y){    if(x.x!=y.x)        return x.x<y.x;    else         return x.k<y.k;}int to(int x){    return x&-x;}int add(int x,int v){    x+=2;    while(x<=N)    {        sum[x]+=v;        x+=to(x);    }}int find(int x){    x+=2;    int num=0;    while(x)    {        num+=sum[x];        x-=to(x);    }    return num;}int dg(int l,int r){    if(l==r) return 0;    int mid=(l+r)/2;    dg(l,mid);    dg(mid+1,r);    tot=0;    for(int i=l;i<=mid;i++)        if(!re[i][0])        {            d[++tot].x=re[i][1];            d[tot].x1=re[i][2];            d[tot].y1=re[i][4];            d[tot].k=0;            d[tot].v=1;            d[tot].be=i;            d[++tot].x=re[i][3];            d[tot].x1=re[i][2];            d[tot].y1=re[i][4];            d[tot].k=2;            d[tot].v=-1;            d[tot].be=i;        }    for(int i=mid+1;i<=r;i++)        if(re[i][0])        {            d[++tot].k=1;            d[tot].x=re[i][1];            d[tot].x1=re[i][2];            d[tot].be=i;        }    sort(d+1,d+1+tot,cmp);    for(int i=1;i<=tot;i++)    {        if(!d[i].k)        {            add(d[i].x1,d[i].v);            add(d[i].y1+1,-d[i].v);        }        else        if(d[i].k==2)        {            add(d[i].x1,d[i].v);            add(d[i].y1+1,-d[i].v);        }        else            ans[d[i].be]+=find(d[i].x1);    }}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)    {        for(int j=0;j<=2;j++) scanf("%d",&re[i][j]);        if(!re[i][0]) scanf("%d%d",&re[i][3],&re[i][4]);    }    dg(1,n);    for(int i=1;i<=n;i++)        if(re[i][0])            printf("%d\n",ans[i]);}
1 0
原创粉丝点击