Live2d Test Env

zoj3961(区间问题)

点击打开zoj1961Let's Chat

Time Limit: 1 Second      Memory Limit:65536 KB

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 ≤mn),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,ira,in), 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,irb,in), 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;
}
(当然,本题任然不需要排序)



如有错误,感谢指出

posted @ 2017-09-27 21:06  nimphy  阅读(112)  评论(0编辑  收藏  举报