首先,这是一个线段树。
但数据范围是10000000 ,线段树开太大会爆掉诶。。。。。。所以需要离散化。
本人跟离散化不熟,使用了大众的离散化。
样例:
5 1 4 2 6 8 10 3 4 7 10
i:1 2 3 4 5 6 7 8 9 10
x[]:1 4 2 6 8 10 3 4 7 10
排序并去重 i:1 2 3 4 5 6 7 8
x[i]:1 2 3 4 6 7 8 10
这样就小了好多啊。但又有一个问题了,看一组样例:
3
1 10
1 4
1 6
正确答案是3,而按这个数组做的话答案为2,因此我们要把间隔大于1的两个数之间加一个数,本人用的就是平均数了。
剩下的大家一看就懂了。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define inf 100005 int Case,n; int zuo[inf],you[inf],x[inf*2],xx[inf*3]; int hash[10000000]; int cnt; int ans; int tree[inf*4],vis[inf*2]; void pushdown(int node) { if(tree[node]) { tree[node<<1]=tree[node]; tree[node<<1|1]=tree[node]; tree[node]=0; } } void build(int l,int r,int node) { tree[node]=0; if(l==r) { return ; } int mid=(l+r)>>1; build(l,mid,node<<1); build(mid+1,r,node<<1|1); } void update(int l,int r,int st,int en,int x,int node) { if(st>=l&&en<=r) { tree[node]=x; return ; } pushdown(node); int mid=(st+en)>>1; if(l<=mid)update(l,r,st,mid,x,node<<1); if(mid<r)update(l,r,mid+1,en,x,node<<1|1); } void query(int l,int r,int node) { if(tree[node]) { if(vis[tree[node]]==0) { ans++; } vis[tree[node]]=1; return ; } if(l==r)return ; int mid=(l+r)>>1; query(l,mid,node<<1); query(mid+1,r,node<<1|1); } void init() { memset(xx,0,sizeof(xx)); memset(x,0,sizeof(x)); memset(vis,0,sizeof(vis)); memset(hash,0,sizeof(hash)); ans=0; cnt=0; } int main() { scanf("%d",&Case); while(Case--) { init(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d %d",&zuo[i],&you[i]); x[++cnt]=zuo[i]; x[++cnt]=you[i]; } sort(x+1,x+1+cnt); int len=unique(x+1,x+1+cnt)-x-1;//去重 int a=0; for(int i=2;i<=len;i++) { if(x[i]-x[i-1]>=2) { xx[++a]=x[i-1]; xx[++a]=(x[i]+x[i-1])>>1; }else { xx[++a]=x[i-1]; } } xx[++a]=x[len];//不知道是不是麻烦了点。。。 for(int i=1;i<=a;i++) { hash[xx[i]]=i; } build(1,a,1); for(int i=1;i<=n;i++) { update(hash[zuo[i]],hash[you[i]],1,a,i,1); } query(1,a,1); printf("%d\n",ans); } }