码迷,mamicode.com
首页 > 其他好文 > 详细

Picture

时间:2017-03-12 21:17:32      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:tree   线段树   clu   amp   data   sso   题目   cstring   add   

线段树+扫描线

对于每条线段,分横竖考虑,排序,坐标第一关键字,左右第2关键字

对于矩形左边线段,先统计这条线段区域0的个数,在把线段树中这条线段覆盖的区域+1,右边反过来

一定要记得右端点-1(因为题目给的是点,实际上是区间)

例如1,3。其实只覆盖2个区间(1,2;2,3)

#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
using namespace std; 
struct data1{ 
    int l,r,k,p; 
}x[10001],y[10001]; 
struct data2{ 
    int x,s,l,r,la; 
}tree[80001]; 
int n; 
bool cmp(data1 a,data1 b) 
    if(a.k==b.k)return a.p>b.p; 
    return a.k<b.k; 
void down(int x) 
    tree[x*2].x+=tree[x].la; 
    tree[x*2].la+=tree[x].la; 
    tree[x*2+1].x+=tree[x].la; 
    tree[x*2+1].la+=tree[x].la; 
    tree[x].la=0; 
void up(int x) 
    tree[x].x=min(tree[x*2].x,tree[x*2+1].x); 
    if(tree[x*2].x==tree[x*2+1].x)tree[x].s=tree[x*2].s+tree[x*2+1].s; 
    if(tree[x*2].x<tree[x*2+1].x)tree[x].s=tree[x*2].s; 
    if(tree[x*2].x>tree[x*2+1].x)tree[x].s=tree[x*2+1].s; 
void init(int x,int l,int r) 
    tree[x].l=l;tree[x].r=r;tree[x].la=0;tree[x].x=0; 
    if(l==r){tree[x].s=1;return;} 
    init(x*2,l,(l+r)/2);init(x*2+1,(l+r)/2+1,r); 
    up(x); 
void add(int x,int l,int r,int k) 
    if(tree[x].l==l&&tree[x].r==r){tree[x].x+=k;tree[x].la+=k;return;} 
    down(x); 
    int mid=(tree[x].l+tree[x].r)/2; 
    if(r<=mid)add(x*2,l,r,k); 
    else if(l>mid)add(x*2+1,l,r,k); 
    else {add(x*2,l,mid,k);add(x*2+1,mid+1,r,k);} 
    up(x); 
void query(int x,int l,int r,int &ansx,int &anss) 
    if(tree[x].l==l&&tree[x].r==r) 
    
        if(ansx==tree[x].x)anss+=tree[x].s; 
        if(tree[x].x<ansx)anss=tree[x].s; 
        ansx=min(ansx,tree[x].x);return
    
    down(x); 
    int mid=(tree[x].l+tree[x].r)/2; 
    if(r<=mid)query(x*2,l,r,ansx,anss); 
    else if(l>mid)query(x*2+1,l,r,ansx,anss); 
    else {query(x*2,l,mid,ansx,anss);query(x*2+1,mid+1,r,ansx,anss);} 
int main() 
    scanf("%d",&n); 
    for(int i=1;i<=n;i++) 
    
        int _x1,_y1,_x2,_y2; 
        scanf("%d%d%d%d",&_x1,&_y1,&_x2,&_y2); 
        _x1+=10000;_x2+=10000;_y1+=10000;_y2+=10000; 
        y[i*2-1].l=_x1;y[i*2-1].r=_x2-1;y[i*2-1].k=_y1;y[i*2-1].p=1; 
        y[i*2].l=_x1;y[i*2].r=_x2-1;y[i*2].k=_y2;y[i*2].p=-1; 
        x[i*2-1].l=_y1;x[i*2-1].r=_y2-1;x[i*2-1].k=_x1;x[i*2-1].p=1; 
        x[i*2].l=_y1;x[i*2].r=_y2-1;x[i*2].k=_x2;x[i*2].p=-1; 
    
    n*=2;int ans=0; 
    sort(x+1,x+n+1,cmp);sort(y+1,y+n+1,cmp); 
    init(1,0,20000); 
    for(int i=1;i<=n;i++) 
    
        if(x[i].p==-1)add(1,x[i].l,x[i].r,-1); 
        int anss=0,ansx=999999999;query(1,x[i].l,x[i].r,ansx,anss); 
        if(x[i].p==1)add(1,x[i].l,x[i].r,1); 
        if(ansx==0)ans+=anss; 
    
    init(1,0,20000); 
    for(int i=1;i<=n;i++) 
    
        if(y[i].p==-1)add(1,y[i].l,y[i].r,-1); 
        int anss=0,ansx=999999999;query(1,y[i].l,y[i].r,ansx,anss); 
        if(y[i].p==1)add(1,y[i].l,y[i].r,1); 
        if(ansx==0)ans+=anss; 
    
    cout<<ans;return 0; 
}  

Picture

标签:tree   线段树   clu   amp   data   sso   题目   cstring   add   

原文地址:http://www.cnblogs.com/lher/p/6539214.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!