【NOIP2014模拟10.25A组】画矩形

题目

这里写图片描述

分析

由于要求按时间顺序来操作,考虑整体二分:
对于一段二分出来的区间,将左区间的修改和右区间的查询取出来,每次更新每个查询的答案,正确性显然。
现在有一对修改和查询的操作(保证所有的查询都在修改之后),按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]);
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9071414.html