安徽省2016“京胜杯”程序设计大赛_G_木条染色
木条染色
Time Limit: 1000 MS | Memory Limit: 65536 KB |
Total Submissions: 134 | Accepted: 20 |
Description
小明是一个非常浪漫的画家,他喜欢画各种奇奇怪怪的画,虽然没人理解他画的究竟是什么东西。
有一天,他突发奇想,对于一根木条,他每次从木条中选取一个区间[l,r]进行染色,经过多次染色后,他想知道在[a,b]区间中有几个未被染色的子区间?
可惜小明虽然画画非常厉害,但是并不擅长解决这类问题,于是,他拿着这根木条来找你,希望你能够给他帮助。
假设木条无限长,所有查询都在木条长度范围内,未被染色的子区间是指,木条上染过色的区间的间断部分。
Input
第一行一个整数T,代表数据组数。
对于每组数据,第一行给出两个整数n,q,分别代表染色的区间个数,以及查询个数。
之后n行,每行两个整数l,r,表示将l到r的区间进行染色,包含l,r两个节点。
之后q行,每行两个整数a,b,表示询问a到b总共有多少未被染色的子区间。
两组数据之间用一个空行隔开。
T<20
n<10000
q<100000
0<=l<r<1000000
0<=a<=b<1000000
Output
对于每次询问,输出一个整数,表示查询结果。
每组数据之后,请输出一个空行。
Sample Input
2
2 3
1 2
3 4
1 3
3 4
5 5
3 3
1 5
2 8
5 6
0 5
0 9
9 9
2 3
1 2
3 4
1 3
3 4
5 5
3 3
1 5
2 8
5 6
0 5
0 9
9 9
Sample Output
1
0
1
1
2
1
0
1
1
2
1
Hint
对于第一组数据,[0,1),(2,3),(4,+)是未染色的子区间,因此查询[1,3]可以找到(2,3)这个子区间,而对于[3,4]不能找到,对于[5,5]可以找到[5,5]。
对于第二组数据,[0,1)和(8,+)是未染色的子区间,因此对于[0,5]只有子区间[0,1),对于查询[0,9],有子区间[0,1)和(8,9],对于查询[9,9],有[9,9]这个子区间。
//这道题还木有做出来,正在努力A中,欢迎各位朋友给出解题思路
2017-4-29 19:02:19----补下这道题的题解,这道题用的是线段是+离散化,代码参考如下
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define lson i<<1 #define rson (i<<1)+1 int maxn,t,n,m; int va[500000]; int ha[1000005],pre,pre2; struct node{ int x,y; }b[100005]; int a[100005]; void build(int i,int l,int r) { va[i] = 1; if(l==r)return; build(lson,l,(l+r)/2); build(rson,(l+r)/2+1,r); } inline void pushUp(int i) { if(va[lson]==va[rson])va[i] = va[lson]; else va[i] = -1; } inline void pushDown(int i) { va[lson] = va[i]; va[rson] = va[i]; } void update(int i,int l,int r,int L,int R) { if(l==L&&r==R) { va[i] = 0; return ; } if(va[i]!=-1)pushDown(i); if(R<=(l+r)/2)update(lson,l,(l+r)/2,L,R); else if(L>=(l+r)/2+1)update(rson,(l+r)/2+1,r,L,R); else { update(lson,l,(l+r)/2,L,(l+r)/2); update(rson,(l+r)/2+1,r,(l+r)/2+1,R); } pushUp(i); } int query(int i,int l,int r,int L,int R) { if(va[i]!=-1) { return va[i]; } if(R<=(l+r)/2)return query(lson,l,(l+r)/2,L,R); else if(L>=(l+r)/2+1)return query(rson,(l+r)/2+1,r,L,R); else return query(lson,l,(l+r)/2,L,(l+r)/2) + query(rson,(l+r)/2+1,r,(l+r)/2+1,R); } inline void init() { pre = 2; sort(a,a+2*n); ha[a[0]] = pre; for(int i=1;i<2*n;i++) if(a[i]>a[i-1]) { pre+=2; ha[a[i]] = pre; } pre2 = 1; for(int i=max(a[0]-1,0);i<=a[2*n-1]+2;i++) if(ha[i]) { pre2 = ha[i]+1; } else ha[i] = pre2; } int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d%d",&a[i*2],&a[i*2+1]); b[i].x = a[i*2]; b[i].y = a[i*2+1]; } init(); build(1,1,pre2); for(int i=0;i<n;i++) update(1,1,pre2,ha[b[i].x],ha[b[i].y]); for(int i=0;i<m;i++) { int c,d; c = max(c,max(0,a[0]-1)); d = min(a[2*i-1]+2,d); scanf("%d%d",&c,&d); printf("%d\n",query(1,1,pre2,ha[c],ha[d])); } for(int i=max(a[0]-1,0);i<=a[2*n-1]+2;i++) ha[i] = 0; if(t!=0)printf("\n"); } return 0; }