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;
}
(当然,本题任然不需要排序)
如有错误,感谢指出