• POJ-3067 Japan---树状数组逆序对变形


    题目链接:

    https://vjudge.net/problem/POJ-3067

    题目大意:

    日本岛东海岸与西海岸分别有N和M个城市,现在修高速公路连接东西海岸的城市,求交点个数。

    解题思路:

    记每条告诉公路为(x,y), 即东岸的第x个城市与西岸的第y个城市修一条路。当两条路有交点时,满足(x1-x2)*(y1-y2) < 0。所以,将每条路按x从小到达排序,若x相同,按y从小到大排序。 然后按排序后的公路用树状数组在线更新,求y的逆序数之和 即为交点个数。

    比如样例

    1 4
    2 3
    3 2
    3 1

    排完序后

    1 4
    2 3
    3 1
    3 2

    1、加入1 4,此时比4大的元素为0,交点数目为0

    2、加入2 3,此时比3大的元素数目为1,交点数目为1

    3、加入3 1,此时比1大的数字有两个,交点数目为3

    4、加入3 2,此时比2大的数字有2个,交点数目为5

    如果先加人3 2,再加入3 1的话会导致3 1这条计算交点的时候吧3 2算进去,但实际上并没有交点,所以排序顺序在x相同的y从小到大排序

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<map>
     6 #include<set>
     7 #include<cmath>
     8 #include<algorithm>
     9 using namespace std;
    10 typedef long long ll;
    11 const int maxn = 1000000 + 10;
    12 int n, m, T, k, cases;
    13 struct node
    14 {
    15     int x, y;
    16     bool operator <(const node& a)const
    17     {
    18         return x < a.x || x == a.x && y < a.y;
    19     }
    20 };
    21 node a[maxn];
    22 int tree[10000];
    23 int lowbit(int x)
    24 {
    25     return x & (-x);
    26 }
    27 ll sum(int x)
    28 {
    29     ll ans = 0;
    30     while(x)
    31     {
    32         ans += tree[x];
    33         x -= lowbit(x);
    34     }
    35     return ans;
    36 }
    37 void add(int x, int d)
    38 {
    39     while(x <= m)
    40     {
    41         tree[x] += d;
    42         x += lowbit(x);
    43     }
    44 }
    45 int main()
    46 {
    47     cin >> T;
    48     while(T--)
    49     {
    50         cin >> n >> m >> k;
    51         memset(tree, 0, sizeof(tree));
    52         for(int i = 1; i <= k; i++)
    53         {
    54             scanf("%d%d", &a[i].x, &a[i].y);
    55         }
    56         sort(a + 1, a + 1 + k);
    57         ll ans = 0;
    58         for(ll i = 1; i <= k; i++)
    59         {
    60             add(a[i].y, 1);
    61             ans += (i - sum(a[i].y));
    62         }
    63         printf("Test case %d: %lld
    ", ++cases, ans);
    64     }
    65     return 0;
    66 }
  • 相关阅读:
    android学习笔记----启动模式与任务栈(Task)
    二叉搜索树转化成双向链表
    复杂链表的复制
    判断是否为二叉搜索树的后序遍历序列
    树的子结构
    调整数组顺序使奇数位于偶数前面,且奇数之间、偶数之间的相对位置不变
    android学习笔记----HandlerThread学习
    android学习笔记----Handler的使用、内存泄漏、源码分析等一系列问题
    原因分析——cin,coutTLE,scanf,printf就AC
    洛谷P1618_三连击(升级版)
  • 原文地址:https://www.cnblogs.com/fzl194/p/8946869.html
Copyright © 2020-2023  润新知