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\n", ++cnt, res); } return 0; }