POJ-3067-Japan

链接:https://vjudge.net/problem/POJ-3067#author=snake52996

题意:

一条河的左边有n个点右边有m个点,给你k条线

以l,y形式,表示左边编号为l的点和右边编号为r的点连起来。

求两条线相交的交点个数

思路:

树状数组,

先按r排序,小的在前,再按l排序,小的在前,保证两个r相同时先考虑靠前的点,不会影响到后面结果。

代码:

#include <iostream>
#include <memory.h>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <queue>
#include <string>
#include <stack>
#include <iterator>
#include <stdlib.h>
#include <time.h>
#include <assert.h>

using namespace std;
typedef long long LL;

const int MAXN = 5e5+10;
int c[MAXN];
int n, m, k;

struct Node
{
    int s, e;
    bool operator < (const Node & that)const
    {
        if (this->e != that.e)
            return this->e < that.e;
        return this->s < that.s;
    }
}node[2*MAXN];

int Lowbit(int k)
{
    return k&(-k);
}

void Add(int x, int v)
{
    while (x <= n)
    {
        c[x] += v;
        x += Lowbit(x);
    }
}

int Sum(int x)
{
    int res = 0;
    while (x > 0)
    {
        res += c[x];
        x -= Lowbit(x);
    }
    return res;
}

int main()
{
    int t, cnt = 0;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d%d", &n, &m, &k);
        memset(c, 0, sizeof(c));
        for (int i = 1;i <= k;i++)
        {
            scanf("%d%d", &node[i].s, &node[i].e);
        }
        sort(node+1, node+1+k);
        LL res = 0;
        Add(node[1].s, 1);
        for (int i = 2;i <= k;i++)
        {
            res += (i-1)-Sum(node[i].s);
            Add(node[i].s, 1);
        }
        printf("Test case %d: %lld
", ++cnt, res);
    }
    return 0;
}