POJ-3067 Japan(树状数组、线段树)

题目链接

Description

Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <= 1000, N <= 1000). K superhighways will be build. Cities on each coast are numbered 1, 2, … from North to South. Each superhighway is straight line and connects city on the East coast with city of the West coast. The funding for the construction is guaranteed by ACM. A major portion of the sum is determined by the number of crossings between superhighways. At most two superhighways cross at one location. Write a program that calculates the number of the crossings between superhighways.

Input

The input file starts with T - the number of test cases. Each test case starts with three numbers – N, M, K. Each of the next K lines contains two numbers – the numbers of cities connected by the superhighway. The first one is the number of the city on the East coast and second one is the number of the city of the West coast.

Output

For each test case write one line on the standard output:
Test case (case number): (number of crossings)

Sample Input

1

3 4 4

1 4

2 3

3 2

3 1

Sample Output

Test case 1: 5

题意

日本有东西两个海岸,东海岸有N个城市,西海岸有M个城市。城市之间一共修了K条路,问一共有几个交点。
当两条路A、B,A的左端点小于B的左端点,A的右端点大于B的右端点时相交。
所以先按照左端点排序,剩下的就是求逆序数。

AC

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <map>
#include <bitset>
#include <set>
#include <string.h>
#include <cmath>
#include <queue>
#include <algorithm>
#define N 1005
#define P pair<int,int>
#define ll long long
#define lowbit(a) a&(-a)
#define pb(a) push_back(a)
#define mk(a, b) make_pair(a, b)
#define mem(a, b) memset(a, b, sizeof(a))
#define read(a) scanf("%d", &a)
#define print(a) printf("%d\n", a)
using namespace std;
ll c[N];
ll getsum(int x) {
    ll ret = 0;
    while (x) {
        ret += c[x];
        x -= lowbit(x);
    }
    return ret;
}
void update(int x) {
    while (x < N) {
        c[x]++;
        x += lowbit(x);
    }
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int t;
    scanf("%d", &t);
    int Case =  1;
    while (t--) {
        mem(c, 0);
        int n, m, k;
        scanf("%d%d%d", &n, &m, &k);
        vector<P> a(k);
        for (int i = 0; i < k; ++i) {
            scanf("%d%d", &a[i].first, &a[i].second);
        }
        // 按照左端点升序,左端点相同又端点升序
        sort(a.begin(), a.end());
        ll ans = 0;
        for (int i = 0; i < k; ++i) {
            ans += getsum(N) - getsum(a[i].second);
            update(a[i].second);
        }
        printf("Test case %d: %lld\n", Case++, ans);
    }
    return 0;
}
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <map>
#include <bitset>
#include <set>
#include <string.h>
#include <cmath>
#include <queue>
#include <algorithm>
#define N 4005
#define P pair<int,int>
#define ll long long
#define lowbit(a) a&(-a)
#define mk(a, b) make_pair(a, b)
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;

struct node{
    ll val;
}segtree[N];
void build(int root, int start, int end) {
    if (start == end)
        segtree[root].val = 0;
    else {
        int mid = (start + end) / 2;
        build(root * 2 + 1, start, mid);
        build(root * 2 + 2, mid + 1, end);
        segtree[root].val = segtree[root * 2 + 1].val + segtree[root * 2 + 2].val;
    }
}

void update(int root, int start, int end, int index) {
    if (index > end || index < start)
        return;
    if (start == end) {
        if (start == index) {
            segtree[root].val++;
        }
        return;
    }
    int mid = (start + end) / 2;
    update(root * 2 + 1, start, mid, index);
    update(root * 2 + 2, mid + 1, end, index);
    segtree[root].val = segtree[root * 2 + 1].val + segtree[root * 2 + 2].val;
}
ll query(int root, int start, int end, int qstart, int qend) {
    if (qstart > end || qend < start)
        return 0;
    if (start >= qstart && end <= qend) {
        return segtree[root].val;
    }
    int mid = (start + end) / 2;
    return query(root * 2 + 1, start, mid, qstart, qend) + query(root * 2 + 2, mid + 1, end, qstart, qend);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int t;
    scanf("%d", &t);
    int Case =  1;
    while (t--) {
        int n, m, k;
        scanf("%d%d%d", &n, &m, &k);
        vector<P> a(k);
        for (int i = 0; i < k; ++i) {
            scanf("%d%d", &a[i].first, &a[i].second);
        }
        // 按照左端点升序,左端点相同又端点升序
        sort(a.begin(), a.end());
        build(0, 0, m + 1);
        ll ans = 0;
        for (int i = 0; i < k; ++i) {
            // 如果查询当前点,可能会被前面的区间包含
            ans += query(0, 0, m + 1, a[i].second + 1, m + 1);
            update(0, 0, m + 1, a[i].second);
        }
        printf("Test case %d: %lld\n", Case++, ans);
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/henuyh/article/details/81213855