【STSRM13】绵津见

【算法】扫描线:差分+树状数组

【题意】转化模型后:求每个矩形覆盖多少点和每个点被多少矩形覆盖。n<=10^5。

【题解】经典的扫描线问题(二维偏序,二维数点)。

数点问题

将所有询问离线并离散化,然后按从上到下排序。

对于点被覆盖问题:

扫描线从上到下进行,遇到矩阵上边界维护区间加,遇到矩阵下边界维护区间减,也就是差分,遇到点单点查询。

每行的排序顺序是{矩阵加,点,矩阵减}。

可以线段树区间维护,也可以树状数组每行各自差分。

对于矩阵覆盖问题:

扫描线从上到下进行,遇到点单点加,遇到矩阵上边界查询区间点数,遇到矩阵下边界查询区间点数并减去上边界区间点数得到一个答案。

每行的排序顺序是{矩阵加,点,矩阵减}。

线段树和树状数组皆可。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
const int maxn=300010;
struct cyc1{int t,x;}a[maxn];
struct cyc2{int t,l,r,y;}b[maxn];
struct cyc{int x,y,y2,id,kind;}q[maxn];
int t[maxn],n,m,mx,my,tot,c[maxn],d[maxn],ans[maxn];
int read()
{
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c=='-')t=-1;
    do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    return s*t;
}
bool cmp(cyc a,cyc b)
{return a.x==b.x?a.kind>b.kind:a.x<b.x;}
bool cmp2(cyc a,cyc b)
{return a.x==b.x?a.kind>b.kind:a.x<b.x;}
int lowbit(int x){return x&(-x);}
void modify(int x,int k){for(int i=x;i<=my;i+=lowbit(i))t[i]+=k;}
int find(int x){int ans=0;for(int i=x;i>=1;i-=lowbit(i))ans+=t[i];return ans;}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int u=read(),v=read();
        a[i]=(cyc1){u,v};
        c[++mx]=u;
        d[++my]=v;
    }
    for(int i=1;i<=m;i++){
        int u=read(),v=read(),w=read(),z=read();
        b[i]=(cyc2){u,v,w,z};
        c[++mx]=u-z;c[++mx]=u+z;
        d[++my]=v;d[++my]=w;
    }
    sort(c+1,c+mx+1);sort(d+1,d+my+1);
    mx=unique(c+1,c+mx+1)-c-1;
    my=unique(d+1,d+my+1)-d-1;
    for(int i=1;i<=n;i++){
        q[++tot]=(cyc){lower_bound(c+1,c+mx+1,a[i].t)-c,lower_bound(d+1,d+my+1,a[i].x)-d,0,i,0};
    }
    for(int i=1;i<=m;i++){
        q[++tot]=(cyc){lower_bound(c+1,c+mx+1,b[i].t-b[i].y)-c,lower_bound(d+1,d+my+1,b[i].l)-d,lower_bound(d+1,d+my+1,b[i].r)-d,i,1};
        tot++;q[tot]=q[tot-1];q[tot].x=lower_bound(c+1,c+mx+1,b[i].t+b[i].y)-c;q[tot].kind=-1;
    }
    sort(q+1,q+tot+1,cmp);
    for(int i=1;i<=tot;i++){
        if(q[i].kind){modify(q[i].y,q[i].kind);modify(q[i].y2+1,-q[i].kind);}
        else ans[q[i].id]=find(q[i].y);
    }
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);printf("\n");
    sort(q+1,q+tot+1,cmp2);
    memset(t,0,sizeof(t));
    for(int i=1;i<=tot;i++){
        if(q[i].kind){
            if(q[i].kind==1)ans[q[i].id]=find(q[i].y2)-find(q[i].y-1);
            else ans[q[i].id]=find(q[i].y2)-find(q[i].y-1)-ans[q[i].id];
        }
        else modify(q[i].y,1);
    }
    for(int i=1;i<=m;i++)printf("%d ",ans[i]);
    return 0;
}
View Code

 

posted @ 2017-08-11 21:28  ONION_CYC  阅读(447)  评论(0编辑  收藏  举报