BZOJ 1818: [Cqoi2010]内部白点 扫描线+树状数组
问题转化为求每一个极长横线段与极长纵线段的交点个数.
这个东西用扫描线+树状数组维护一下就可以了.
code:
#include <cstdio> #include <algorithm> #define N 200005 #define setIO(s) freopen(s".in","r",stdin) using namespace std; namespace BIT { int C[N]; int lowbit(int t) { return t&(-t); } void update(int x,int v) { for(;x<N;x+=lowbit(x)) C[x]+=v; } int query(int x) { int tmp=0; for(;x>0;x-=lowbit(x)) tmp+=C[x]; return tmp; } }; struct Point { int x,y; Point(int x=0,int y=0):x(x),y(y){} }point[N]; struct Line { int x,y,z,pri; Line(int x=0,int y=0,int z=0,int pri=0):x(x),y(y),z(z),pri(pri){} }line[N<<1]; bool cmpy(Point a,Point b) { return a.y==b.y?a.x<b.x:a.y<b.y; } bool cmpx(Point a,Point b) { return a.x==b.x?a.y<b.y:a.x<b.x; } bool cmpl(Line a,Line b) { return a.x==b.x?a.pri<b.pri:a.x<b.x; } int A[N]; int main() { // setIO("input"); int i,j,n,cnt=0,ans=0; scanf("%d",&n); for(i=1;i<=n;++i) { scanf("%d%d",&point[i].x,&point[i].y); A[i]=point[i].y; } sort(A+1,A+1+n); for(i=1;i<=n;++i) { point[i].y=lower_bound(A+1,A+1+n,point[i].y)-A; } sort(point+1,point+1+n,cmpy); for(i=1;i<=n;i=j+1) { j=i; while(j<n&&point[j+1].y==point[i].y) ++j; line[++cnt]=Line(point[i].x,point[i].y,0,1); line[++cnt]=Line(point[j].x,point[j].y,0,3); } sort(point+1,point+1+n,cmpx); for(i=1;i<=n;i=j+1) { j=i; while(j<n&&point[j+1].x==point[i].x) ++j; line[++cnt]=Line(point[i].x,point[j].y,point[i].y,2); } sort(line+1,line+1+cnt,cmpl); for(i=1;i<=cnt;++i) { if(line[i].pri==2) { ans+=BIT::query(line[i].y)-BIT::query(line[i].z-1); } else { if(line[i].pri==1) BIT::update(line[i].y,1); else BIT::update(line[i].y,-1); } } printf("%d\n",ans); return 0; }