题意:给定N个区间,求最后区间内最长连续区间的长度以及最长不覆盖的长度
分析:本来是可以直接暴力的,可是想练一下最近线段树到底做得怎么样了,所以就用线段树试了一下,哎,改了俩个多小时,终于出来了。
注意:对区间长度的概念还是……因为离散化之后区间长度的求法变了,所以再求半个区间长度的时候,出错了
/* ID: nanke691 LANG: C++ TASK: milk2 */ #include<iostream> #include<fstream> #include<algorithm> #include<string.h> #define maxn 20000 using namespace std; int lb[maxn*3],rb[maxn*3],len1[maxn*3],len2[maxn*3],cnt[maxn*3]; int lb1[maxn*3],rb1[maxn*3]; int map[maxn<<2]; //lb[]表示该区间内左边连续覆盖的长度,rb[]该区间内右边连续覆盖的长度,len1[]该区间内连续覆盖的长度; //len2[],该区间内连续的空区间的长度,lb1[]该区间内左边连续不覆盖的长度,rb1[]该区间内右边连续不覆盖的长度 //cnt[]表示该区间是否被全部覆盖 struct seg { int x,y; }ss[maxn]; void build(int k,int s,int t) { lb[k]=rb[k]=len1[k]=0; cnt[k]=0; lb1[k]=rb1[k]=len2[k]=map[t+1]-map[s]; if(s==t) return ; int kl=k<<1,kr=kl+1,mid=(s+t)>>1; build(kl,s,mid); build(kr,mid+1,t); } int Bin(int n,int key) { int left=0,right=n-1; while(left<=right) { int mid=(left+right)>>1; if(map[mid]==key) return mid; if(map[mid]<key) left=mid+1; else right=mid-1; } return -1; } void PushUp(int k,int s,int t) { int l=map[t+1]-map[s]; int mid=(s+t)>>1; int ml=map[mid+1]-map[s]; lb1[k]=lb1[k<<1]; rb1[k]=rb1[k<<1|1]; lb[k]=lb[k<<1]; rb[k]=rb[k<<1|1]; if(lb1[k<<1]== ml)//左边空区间长度等于左儿子的整个区间长度 lb1[k]+=lb1[k<<1|1]; if(lb[k<<1]== ml)//下面类似 lb[k]+=lb[k<<1|1]; if(rb1[k<<1|1]==l-ml) rb1[k]+=rb1[k<<1]; if(rb[k<<1|1]==l-ml) rb[k]+=rb[k<<1]; len2[k]=max(rb1[k<<1]+lb1[k<<1|1],max(len2[k<<1],len2[k<<1|1])); len1[k]=max(rb[k<<1]+lb[k<<1|1],max(len1[k<<1],len1[k<<1|1])); } void update(int k,int l,int r,int s,int t) { if(l<=s && t<=r) { cnt[k]=1; lb[k]=rb[k]=len1[k]=map[t+1]-map[s]; rb1[k]=lb1[k]=len2[k]=0; return ; } if(cnt[k]==1) return ; int kl=k<<1,kr=kl+1,mid=(s+t)>>1; if(l<=mid) update(kl,l,r,s,mid); if(r>mid) update(kr,l,r,mid+1,t); PushUp(k,s,t); } int main() { int n,m,a,b; FILE *fin = fopen ("milk2.in", "r"); FILE *fout = fopen ("milk2.out", "w"); fscanf(fin,"%d",&n); //scanf("%d",&n); m=0; for(int i=0;i<n;i++) { fscanf(fin,"%d %d",&ss[i].x,&ss[i].y); //scanf("%d %d",&ss[i].x,&ss[i].y); map[m++]=ss[i].x; map[m++]=ss[i].y; } sort(map,map+m); int k=1; for(int i=1;i<m;i++) if(map[i]!=map[i-1]) map[k++]=map[i]; build(1,0,k-2); for(int i=0;i<n;i++) { int l=Bin(k,ss[i].x); int r=Bin(k,ss[i].y)-1; if(l<=r) update(1,l,r,0,k-2); } fprintf(fout,"%d %d\n",len1[1],len2[1]); // printf("%d %d\n",len1[1],len2[1]); }