Greetings

号码线上有n个人;第i个人在ai点并且想要去bi点。对于每个人,ai<bi,所有人的起点和终点都是不同的。(也就是说,所有2n个数字a1、a2、…、an、b1、b2、…、bn都是不同的。)
所有人都将以每秒1个单位的速度同时移动,直到到达终点bi。当两个人在同一地点见面时,他们会互相问候一次。会有多少问候?请注意,一个人仍然可以问候其他人,即使他们已经到达了最后一点。

Input
输入的第一行包含一个整数t(1 ≤ t ≤ 1e4)——测试用例的数量。测试用例的描述如下。
每个测试用例的第一行包含一个整数n(1 ≤ n ≤ 2e5)——人数。
接下来是n行,其中第i行包含两个整数ai和bi(−1e9 ≤ ai<bi ≤ 1e9)——每个人的起始和结束位置。
对于每个测试用例,所有2n个数字a1、a2、…、an、b1、b2、…、bn都是不同的。
所有测试用例的n之和不超过2e5。

Output
输出对于每个测试用例,输出一个整数,表示将要发生的问候语的数量。

输入
5
2
2 3
1 4
6
2 6
3 9
4 5
1 8
7 10
-2 100
4
-10 10
-5 5
-12 12
-13 13
5
-4 9
-2 5
3 4
6 7
8 10
4
1 2
3 4
5 6
7 8

输出
1
9
6
4
0

解析:
通过分析可以判断出运动的类型有三种情况

Greetings_第1张图片

相离、相交(终点在起点前) 、包含三种情况

可以分析出只有当出现包含关系的时候两人才能相互问候。
 

Greetings_第2张图片

通过画图发现它们之间的关系,当它们按左端点大小的顺序编号后,能过发现它们的右端点和每个人和其他人互相问候的次数的关系成 “逆序对”的关系,即 ibj 的个数.
 

#include 
using namespace std;
#define int long long
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef pair PII;
const double PI=acos(-1.0);
const int N=2e6+10;
int t,n;
struct node
{
    int a,b,id;
}str[N];
bool cmp1(node x,node y)
{
    return x.a=r) return ;
    int mid=l+r>>1;
    merge_sort(l,mid);
    merge_sort(mid+1,r);
    int i=l,j=mid+1,k=0;
    while (i<=mid&&j<=r)
    {
        if (a[i]<=a[j]) tmp[k++]=a[i++];
        else 
        {
            tmp[k++]=a[j++];
            cnt +=mid-i+1;
        }
    }
    while (i<=mid) tmp[k++]=a[i++];
    while (j<=r)   tmp[k++]=a[j++];
    for (i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
}
signed main()
{
    ios;
    cin>>t;
    while (t--)
    {
        cin>>n;
        for (int i=1;i<=n;i++) cin>>str[i].a>>str[i].b;
        sort (str+1,str+n+1,cmp1);
        for (int i=1;i<=n;i++) str[i].id=i;
        sort (str+1,str+n+1,cmp2);
        for (int i=1;i<=n;i++) a[i]=str[i].id;
        cnt=0;
        merge_sort(1,n);
        cout<

你可能感兴趣的:(算法,数据结构)