zoj3961(区间问题)
ACM (ACMers' Chatting Messenger) is a famous instant messaging software developed by Marjar Technology Company. To attract more users, Edward, the boss of Marjar Company, has recently added a new feature to the software. The new feature can be described as follows:
If two users, A and B, have been sending messages toeach other on the lastmconsecutive days, the "friendship point" between them will be increased by 1 point.
More formally, if user A sent messages to user B on each day between the (i -m + 1)-th day and thei-th day (both inclusive), and user B also sent messages to user A on each day between the (i - m + 1)-th day and thei-th day (also both inclusive), the "friendship point" between A and B will be increased by 1 at the end of thei-th day.
Given the chatting logs of two users A and B duringn consecutive days, what's the number of the friendship points between them at the end of then-th day (given that the initial friendship point between them is 0)?
Input
There are multiple test cases. The first line of input contains an integerT (1 ≤T ≤ 10), indicating the number of test cases. For each test case:
The first line contains 4 integers n (1 ≤n ≤ 109),m (1 ≤m ≤n),x andy (1 ≤x,y ≤ 100). The meanings ofn andm are described above, whilex indicates the number of chatting logs about the messages sent by A to B, andy indicates the number of chatting logs about the messages sent by B to A.
For the following x lines, thei-th line contains 2 integersla,i andra,i (1 ≤la,i ≤ra,i ≤n), indicating that A sent messages to B on each day between thela,i-th day and thera,i-th day (both inclusive).
For the following y lines, thei-th line contains 2 integerslb,i andrb,i (1 ≤lb,i ≤rb,i ≤n), indicating that B sent messages to A on each day between thelb,i-th day and therb,i-th day (both inclusive).
It is guaranteed that for all 1 ≤ i <x,ra,i + 1 <la,i + 1 and for all 1 ≤i <y,rb,i + 1 <lb,i + 1.
Output
For each test case, output one line containing one integer, indicating the number of friendship points between A and B at the end of then-th day.
Sample Input
2
10 3 3 2
1 3
5 8
10 10
1 8
10 10
5 3 1 1
1 2
4 5
Sample Output
3
0
Hint
For the first test case, user A and user B send messages to each other on the 1st, 2nd, 3rd, 5th, 6th, 7th, 8th and 10th day. Asm = 3, the friendship points between them will be increased by 1 at the end of the 3rd, 7th and 8th day. So the answer is 3.
Author: WENG, Caizhi
Source: The 14th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple
本题是:扫描线思想
对于此类题需要注意:
一:可能有区间合并
二:可能有区间排序
三:可能有不合法区间
四:对于判断交区间,并不需要很多个if语句判断,具体的,
我们设L=max(a.l,b.l),R=min(a.r.b.r),则做差为并期间,当R-L>0时为我们常见的具体的并区间。
幸运的是本题良心题,不需要排序合并,而且数据小,即便O(xy)也能过
//我的原始代码,拒绝不思考就引用 #include<cstdio> #include<cstdlib> #include<iostream> using namespace std; int n,m,x,y,ans; int l1[105],r1[105],l2[105],r2[105]; void _in() { cin>>n>>m>>x>>y; for(int i=1;i<=x;i++) cin>>l1[i]>>r1[i]; for(int i=1;i<=y;i++) cin>>l2[i]>>r2[i]; } void _find(int a,int b) { int temp,L,R; L=max(l1[a],l2[b]); R=min(r1[a],r2[b]); temp=R-L+1; if(temp>=m) ans+=temp-m+1; } void _solve() { for(int i=1;i<=x;i++) for(int j=1;j<=y;j++){ _find(i,j); } cout<<ans<<endl; } int main() { int t,T; cin>>T; for(t=1;t<=T;t++){ ans=0; _in(); _solve(); } return 0; }
理解起来应该很简单
引申一下,对于这一类扫描线思想题目。
我们的大概步骤是:
1,排序(假定按左a.l为关键词排序)
2,合并(如区间[1,3],[3,5]合并成[1,5].而[1,3],[2,4]合并成[1,4])
3,按右a.r为关键词向右扫描,则本题的复杂度可以降到O(x+y) (应用师兄的代码http://blog.csdn.net/DongChengRong/article/details/70496302)
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; const int maxn=100+20; int n,m,x,y; struct Node { int start,endd; }A[maxn],B[maxn]; /*int cmp(struct Node s1,struct Node s2) { return s1.start<s2.start; }*/ int main() { int test; scanf("%d",&test); for(int i=0;i<test;i++) { scanf("%d%d%d%d",&n,&m,&x,&y); for(int j=1;j<=x;j++) scanf("%d%d",&A[j].start,&A[j].endd); for(int j=1;j<=y;j++) scanf("%d%d",&B[j].start,&B[j].endd); //sort(A+1,A+1+x,cmp); //sort(B+1,B+1+y,cmp); int ans=0,j=1,k=1; while(k<=y && j<=x) { int a,b; if(B[k].start>A[j].endd) { j++; continue; } if(B[k].endd<A[j].start) { k++; continue; } a=max(B[k].start,A[j].start); b=min(B[k].endd,A[j].endd); if(a>n || b>n) break; int date=b-a+1; int point=date+1-m; if(point>=1) ans+=point; if(A[j].endd<B[k].endd) j++; else if(A[j].endd==B[k].endd) { j++; k++;} else k++; } printf("%d\n",ans); } return 0; }
(当然,本题任然不需要排序)
如有错误,感谢指出