树状数组 之 poj 3067

这道题和 poj 2481 极其相似。。。但wa了几次。。。

原因:

1)对于结果和存储树状数组求和的变量,采用 long long 来保存;

2)从东海岸 number x,到西海岸 number y, 可能建了两条高速

(即从位置 x 到位置 y 可能有两条高速)

故在树状数组求 mySum 时,所传参数为 y-1  (详见代码)

解题思路:

设东海岸位置 x ,西海岸位置 y ,使x 升序,若 x 相等,按 y 升序(可模拟所给范例,有助理解)

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long int64;
int64 bit[1005];
int N, M, K;

struct node {int x, y;};

node Arr[1005*1005];

bool Cmp (const node n1, const node n2) {
    if (n1.x == n2.x) { return n1.y > n2.y;}
    else return n1.x > n2.x;
}

int64 mySum(int x)
{
    int64 sum = 0;
    while (x)
    {
        sum += bit[x];
        x -= (x&(-x));
    }
    return sum;
}

void myAdd(int x)
{
    while (x <= 1005)
    {
        bit[x] += 1;
        x += (x&(-x));
    }
}

int64 Solve()
{
    int64 ans = 0;
    for (int i = 0; i < K; i++) {
        ans += mySum(Arr[i].y - 1); // wa 原因2
        myAdd(Arr[i].y);
    }
    return ans;
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int cas = 1; cas <= T; cas++) {
        memset(Arr, 0, sizeof(Arr));
        memset(bit, 0, sizeof(bit));
        scanf("%d %d %d", &N, &M, &K);
        for (int i = 0; i < K; i++) {
            scanf("%d %d", &Arr[i].x, &Arr[i].y);
        }
        sort(Arr, Arr + K, Cmp);
        printf("Test case %d: %lld\n", cas, Solve());
    }
    return 0;
}


posted @ 2014-05-23 21:03  JmingS  阅读(145)  评论(0编辑  收藏  举报