标签: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; } 标签:tree 线段树 clu amp data sso 题目 cstring add
原文地址:http://www.cnblogs.com/lher/p/6539214.html