歌名 - 歌手
0:00

    【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]);
    }
    
    posted @ 2018-05-22 12:13  无尽的蓝黄  阅读(197)  评论(0编辑  收藏  举报