对于区间特别大的 (1~1e7)
但是覆盖次数又特别小的
我们采用离散化..
如样列:
1 4
2 6
8 10
3 4
7 10
把每对拆开 升序排序 去重 得:
1 2 3 4 6 7 8 10
对应序号
1 2 3 4 5 6 7 8
把区间关系用序号的关系来替代:
1 4
2 5
7 8
3 4
6 8
这样 区间是不是就被压缩了呢?
标记:
每个节点有三种值 >0 ==-1 ==0
==0:未被染色 >0:染单色 ==-1:染复色
更新时 不包含:结束 完全包含:直接染色 >=0 改节点为-1并将原色向下推
询问时 遇到==0返回 >0 记录 返回,
#include <cstdio> #include <cstring> #include <algorithm> #include <set> #define gl l,(l+r)>>1,num<<1 #define gr ((l+r)>>1)+1,r,num<<1|1 const int MAXN = 20005; using namespace std; int pa[10005][2],save[MAXN]; short dis[10000005]; bool tag[10005]; short st[10005<<4]; void insert(int v,int a,int b,int l,int r,int num) { if(b<l||a>r) return; if(a<=l&&b>=r) { st[num]=v; return; } if(st[num]>=0) { st[num<<1]=st[num]; st[num<<1|1]=st[num]; st[num]=-1; } insert(v,a,b,gl); insert(v,a,b,gr); } int cnt=0; void calc(int l,int r,int num) { if(!st[num])return; if(st[num]>0) { if(!tag[st[num]]) cnt++,tag[st[num]]=1; return; } calc(gl); calc(gr); } int main() { //freopen("a.in","r",stdin); int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); memset(dis,0,sizeof(dis)); memset(st,0,sizeof(st)); int num=0; for(int i=0;i<n;i++) { scanf("%d%d",&pa[i][0],&pa[i][1]); if(!dis[pa[i][0]]) save[num++]=pa[i][0]; if(!dis[pa[i][1]]) save[num++]=pa[i][1]; dis[pa[i][0]]++; dis[pa[i][1]]++; } sort(save,save+num); int hash=0; for(int i=0;i<num;i++) dis[save[i]]=(++hash); for(int i=0;i<n;i++) { pa[i][0]=dis[pa[i][0]]; pa[i][1]=dis[pa[i][1]]; insert(i+1,pa[i][0],pa[i][1],1,hash,1); } cnt=0; memset(tag,0,sizeof(tag)); calc(1,hash,1); printf("%d\n",cnt); } return 0; }