POJ此题数据巨水,大家可以到NYOJ上提交以下,看看写的程序到底对不对。这题就是线段树,其次要离散化一下,开线段树数组的时候要注意这点。容易RE。
离散化后找应设值的时候用二分查找,因为总数不多,所以用二分来说是比较快的,之后就是线段树的普通操作了,其中用到了lazy思想。
#include <iostream> #include <cstdio> #include <string.h> #include <algorithm> using namespace std; const int N=10010; struct tree{ int left,right,num; }tt[16*N]; int xx[N*4],yy[4*N],value[4*N],flag[4*N],ans; void built_tree(int lp,int rp,int pos){ tt[pos].left=lp; tt[pos].right=rp; tt[pos].num=0; if(lp==rp)return; int mid=(tt[pos].left+tt[pos].right)/2; built_tree(lp,mid,pos*2); built_tree(mid+1,rp,pos*2+1); } int find(int x,int lp,int rp){ while(lp<=rp){ int mid=(lp+rp)/2; if(value[mid]==x)return mid; else if(value[mid]>x) rp=mid-1; else lp=mid+1; } return -1; } void add(int lp,int rp,int id,int pos){ if(lp<=tt[pos].left&&rp>=tt[pos].right){ tt[pos].num=id; return; } if(tt[pos].num){ tt[2*pos].num=tt[2*pos+1].num=tt[pos].num; tt[pos].num=0; } int mid=(tt[pos].left+tt[pos].right)/2; if(lp<=mid) add(lp,rp,id,pos*2); if(rp>mid) add(lp,rp,id,pos*2+1); } void query(int lp,int rp,int pos){ if(tt[pos].num){ if(!flag[tt[pos].num]){ ans++; flag[tt[pos].num]=1; } return; } if(lp==rp)return; int mid=(tt[pos].left+tt[pos].right)/2; query(lp,mid,2*pos); query(mid+1,rp,2*pos+1); } int main(){ freopen("1.txt","r",stdin); int numcase; scanf("%d",&numcase); while(numcase--){ int n,pos=1; scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d",&xx[i],&yy[i]); value[pos++]=xx[i]; value[pos++]=yy[i]; } //built_tree(1,N,1); //离散化 sort(value+1,value+pos); int kk=2; for(int i=2;i<pos;++i){ if(value[i]!=value[i-1]){ value[kk++]=value[i]; } } for(int i=kk-1;i>1;--i){ if(value[i]!=value[i-1]+1){ value[kk++]=value[i-1]+1; } } sort(value+1,value+kk); built_tree(1,kk-1,1); for(int i=1;i<=n;++i){ int newx=find(xx[i],1,kk-1); int newy=find(yy[i],1,kk-1); add(newx,newy,i,1); } memset(flag,0,sizeof(flag)); ans=0; query(1,kk-1,1); printf("%d\n",ans); } return 0; }