POJ 3067 Japan

将East coast当成x,West coast当成y, 这题需要注意的是两条高速公路交点只能在两条高速公路之间,不能在East coast 或 West coast处.

 

针对以上两种不同的情况排序的规则是不一样的:

<1>计算East coast 和 West coast在内的交点   首先按照 y非增,x非降的顺序进行排序,然后按照排序后的顺序遍历没条高速公路,利用树状数组统计当前高速公路的小于p[i].x的高速公路的条数,最后直接求和即可.

<2>针对情况2,我们采用求补运算的方法  按照 x非降, y非降的顺序进行排序,然后也是利用树状数组进行统计(求补),即可得到交点只在两条高速公路之间的交点的个数.

 

#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <functional>
using namespace std;

//----------------------------------------------------------
#define CL(a,b)       memset(a,b,sizeof(a))
#define CLQ(q)        while(!q.empty())q.pop();
#define FOR(i,a,b)    for(int i=a;i<=b;++i)
#define FD(i,a,b)     for(int i=a;i>=b;--i)
#define FOS(i,a,b,c)  for(int i=a;i<=b;i+=c)
#define FS(i,a)       for(int i=0;a[i];++i)
#define REP(i,n)      for(int i=0;i<n;++i)
#define PR2(a,n,m)    for(int i=0;i<n;++i){for(int j=0;j<m;++j)cout<<a[i][j]<<" ";puts("");}
#define max(a,b)      ((a)>(b)?(a):(b))
#define min(a,b)      ((a)<(b)?(a):(b))
#define checkMax(a,b) {if(a<b)a=b;}
#define checkMin(a,b) {if(a>b)a=b;}
#define READ(a)       freopen(a,"r",stdin)
#define WRITE(a)      freopen(a,"w",stdout)
#define sqr(x)        ((x)*(x))
#define inf           0x3f3f3f3f
#define INF           0x3f3f3f3f3f3f3f3fLL
#define eps           1e-10
typedef long long LL;
const double pi  = acos(-1.0);
const double hpi = asin(1.0);
//-----------------------------------------------------------

/*
const int MAXN = 500010;

struct Node
{
    int pos, val;
    Node() {}
    Node(int t_pos, int t_val) : pos(t_pos), val(t_val) {}
    friend bool operator < (const Node &p1, const Node &p2)
    {
        return p1.val < p2.val;
    }
}p[MAXN];
int reflect[MAXN], Tree[MAXN];
LL ans = 0;
int n;

inline int lowbit(int x)
{
    return x & (-x);
}

void modify(int x, int value)
{
    for(int i = x; i <= n; i += lowbit(i))
    {
        Tree[i] += value;
    }
}

LL getsum(int x)
{
    LL ret = 0;
    for(int i = x; i > 0; i -= lowbit(i))
    {
        ret += 1LL*Tree[i];
    }
    return ret;
}

int main()
{
    //READ("aa.in"); WRITE("bb.out");

    while(scanf("%d", &n) && n)
    {
        ans = 0LL;
        CL(Tree, 0);
        FOR(i, 1, n)
        {
            scanf("%d", &p[i].val);
            p[i].pos = i;
        }
        sort(p + 1, p + n + 1);
        FOR(i, 1, n)
        {
            reflect[p[i].pos] = i;
        }
        FOR(i, 1, n)
        {
            ans += (i - 1 - getsum(reflect[i]));
            modify(reflect[i], 1);
        }
        printf("%lld\n", ans);
        //cout << ans << endl;
    }
    return 0;
}
*/

const int MAXN = 1010;

struct Node
{
    int x, y;
    Node() {}
    Node(int t_x, int t_y) : x(t_x), y(t_y) {}
    friend bool operator < (const Node &p1, const Node &p2)
    {
        if(p1.y == p2.y)
            return p1.x <= p2.x;
        return p1.y <= p2.y;
    }
}p[MAXN*MAXN];
int Tree[MAXN], T, n, N, M, K;
LL ans;

inline int lowbit(int x)
{
    return x & (-x);
}

void modify(int x, int value)
{
    for(int i = x; i <= n; i += lowbit(i))
    {
        Tree[i] += value;
    }
    return ;
}

int getsum(int x)
{
    int ret = 0;
    for(int i = x; i > 0; i -= lowbit(i))
    {
        ret += Tree[i];
    }
    return ret;
}


int main()
{
    //READ("aa.in"); WRITE("bb.out");

    scanf("%d", &T);
    for(int kcase = 1; kcase <= T; ++kcase)
    {
        scanf("%d %d %d", &N, &M, &K);
        for(int i = 1; i <= K; ++i)
        {
            scanf("%d %d", &p[i].x, &p[i].y);
        }
        sort(p + 1, p + K + 1);
        n = N;
        ans = 0; CL(Tree, 0);
        for(int i = 1; i <= K; ++i)
        {
            ans += (i - 1 - getsum(p[i].x));
            modify(p[i].x, 1);
        }
        printf("Test case %d: %lld\n", kcase, ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值