数学模型:给定一个整数序列(最多10000000个数),初始化为0,一共有n(最大10000)个操作,其中第i个操作是将某个指定区间内的数赋值为i,求在经过n次操作后,序列中有多少个不同的非0数
该题可用线段数来做,保存的关键信息为这段的值,最后的查询只有一次。
需要注意的是最多有10000000个数,但n不大,所以可以用离散化处理进行优化。
#include <stdio.h> #include <string.h> #include <stdlib.h> #define N 10001 #define INF 0x7fffffff int a[N],b[N],c[2*N],top; int vis[N]; int id[8*N]; int cmp(const void *a,const void *b) { return (*(int*)a)-(*(int*)b); } int Search(int x) { int mid,min=0,max=top; while(min+1!=max) { mid=(min+max)>>1; if(c[mid]>x) max=mid; else min=mid; } return min; } void pushdown(int cur,int x,int y) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; if(id[cur]) { id[ls]=id[rs]=id[cur]; id[cur]=0; } } void build(int cur,int x,int y) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; id[cur]=0; if(x==y) return; build(ls,x,mid); build(rs,mid+1,y); } void change(int cur,int x,int y,int s,int t,int k) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; if(x>=s && y<=t) { id[cur]=k; return; } pushdown(cur,x,y); if(mid>=s) change(ls,x,mid,s,t,k); if(mid+1<=t) change(rs,mid+1,y,s,t,k); } int get(int cur,int x,int y) { int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1; if(id[cur]) { if(0==vis[id[cur]]) { vis[id[cur]]=1; return 1; } return 0; } if(x==y) return 0; return get(ls,x,mid)+get(rs,mid+1,y); } int main() { int t,n,i; scanf("%d",&t); while(t--) { scanf("%d",&n); top=0; for(i=0;i<n;i++) { scanf("%d%d",&a[i],&b[i]); c[top++]=a[i]; c[top++]=b[i]; } qsort(c,top,sizeof(c[0]),cmp); top=1; for(i=1;c[i];i++) { if(c[i]!=c[top-1]) c[top++]=c[i]; } c[top]=INF; build(1,0,top-1); for(i=0;i<n;i++) { a[i]=Search(a[i]); b[i]=Search(b[i]); change(1,1,top,a[i]+1,b[i]+1,i+1); } memset(vis,0,sizeof(vis[0])*(n+1)); printf("%d\n",get(1,1,top)); } return 0; }