ZOJ 3961 Let's Chat (双指针 + 区间交)

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 to each other on the last m consecutive 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 the i-th day (both inclusive), and user B also sent messages to user A on each day between the (i - m + 1)-th day and the i-th day (also both inclusive), the “friendship point” between A and B will be increased by 1 at the end of the i-th day.

Given the chatting logs of two users A and B during n consecutive days, what’s the number of the friendship points between them at the end of the n-th day (given that the initial friendship point between them is 0)?

给定若干区间 [l, r] 分别表示 A 和 B 在区间内每一天均向对方发送信息。求有多少个不同的连续区间 [i,im+1] ,A 和 B 在区间的每一天均向对方发送了信息。

解题思路

双指针求区间交问题。由于问题保证了 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. 故不需要进行区间合并。

对于 ia 表示的区间 a[ia] 和 ib 表示的区间 b[ib] ,其区间交为 [max(a[ia].first,b[ib].fist),min(a[ia].second,b[ib].second)] 。对答案的贡献为 max(0, -m+1)

之后判断 ia 指针或 ib 指针进行后移,继续判断新的两个区间的交。

代码

#include<bits/stdc++.h>
using namespace std;
int n, m, x, y, ans;
pair<int, int> a[110], b[110], p;
void solve()
{
    ans = 0;
    int ia = 1, ib = 1;
    p.first = max(a[ia].first, b[ib].first);
    while(true)
    {
        p.second = min(a[ia].second, b[ib].second);
        ans += max(0, p.second-p.first+1-m+1);
        if(ia > x || ib > y)  return;
        if(p.second == a[ia].second && ia<=x)
            ia++;
        else if(p.second == b[ib].second && ib<=y)
            ib++;
        p.first = max(a[ia].first, b[ib].first);
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d %d",&n,&m,&x,&y);
        for(int i=1;i<=x;i++)
            scanf("%d %d", &a[i].first, &a[i].second);
        for(int i=1;i<=y;i++)
            scanf("%d %d", &b[i].first, &b[i].second);
        solve();
        printf("%d\n", ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值