• HDU 5792:World is Exploding(树状数组求逆序对)


    http://acm.hdu.edu.cn/showproblem.php?pid=5792

    World is Exploding

    Problem Description
     
    Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: abcd,1a<bn,1c<dn,Aa<Ab,Ac>Ad.
     
    Input
     
    The input consists of multiple test cases. 
    Each test case begin with an integer n in a single line.

    The next line contains n integers A1,A2An.
    1n50000
    0Ai1e9
     
    Output
     
    For each test case,output a line contains an integer.
     
    Sample Input
     
    4
    2 4 1 3
    4
    1 2 3 4
     
    Sample Output
     
    1
    0

     

    Insipired by http://blog.csdn.net/libin66/article/details/52098019

    题意:比较简单直接看。

    思路:分别求出在 i 的时候前面有多少比它小的(即像Aa,Ab这样升序的有多少对),用up记录,后面有多少比它小的(像Ac,Ad这样降序的有多少对),用down记录,然后ans = up * down,因为有很多重复。用树状数组维护四个数组,ls —— 在[1,i-1]有多少比a[i]小的,rs —— 在[i+1,n]有多少比a[i]小的,lb —— 在[1,i-1]有多少比a[i]大的,rb —— 在[i+1,n]有多少比a[i]大的。由容斥原理要减去 (  ls * lb + rs * rb + ls * rs + lb * rb )。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 using namespace std;
     5 #define N 50005
     6 #define MOD 1000000007
     7 typedef long long LL;
     8 LL ls[N], lb[N], rs[N], rb[N], bit[N];
     9 int a[N], num[N], n, m;
    10 
    11 /*
    12 ls和lb是[1,i-1]中比a[i]小的数的数量,比a[i]大的数的数量
    13 rs和rb是[i+1, n]中比a[i]小的数的数量,比a[i]大的数的数量
    14 这些都可以通过树状数组实现
    15 由于答案会多算进去a=c || a=d || b=c || b=d的情况,那么枚举这四种情况减去就可以了(a=c那么必定b!=d,同理其他
    16 a=c:ans-=rs[i]*rb[i]
    17 a=d:ans-=lb[i]*rb[i]
    18 b=c:ans-=ls[i]*rs[i]
    19 b=d:ans-=lb[i]*ls[i]
    20 */
    21 
    22 void init()
    23 {
    24     memset(ls, 0, sizeof(ls));
    25     memset(lb, 0, sizeof(lb));
    26     memset(rs, 0, sizeof(rs));
    27     memset(rb, 0, sizeof(rb));
    28     memset(sum, 0, sizeof(sum));
    29 }
    30 
    31 int lowbit(int x)
    32 {
    33     return x & (-x);
    34 }
    35 
    36 void update(int pos)
    37 {
    38     while(pos <= m) {
    39         bit[pos]++;
    40         pos += lowbit(pos);
    41     }
    42 }
    43 
    44 LL query(int pos)
    45 {
    46     LL ans = 0;
    47     while(pos > 0) {
    48         ans += bit[pos];
    49         pos -= lowbit(pos);
    50     }
    51     return ans;
    52 }
    53 
    54 int main()
    55 {
    56     while(~scanf("%d", &n)) {
    57         init();
    58         for(int i = 1; i <= n; i++) {
    59             scanf("%d", &a[i]);
    60             num[i] = a[i];
    61         }
    62         sort(a+1, a+1+n);
    63         m = unique(a+1, a+1+n) - (a+1);
    64         for(int i = 1; i <= n; i++)
    65             num[i] = lower_bound(a+1, a+1+m, num[i]) - a;
    66 
    67         LL up = 0, down = 0;
    68         memset(bit, 0, sizeof(bit));
    69         for(int i = 1; i <= n; i++) {
    70             ls[i] = query(num[i] - 1);
    71             lb[i] = query(m) - query(num[i]);
    72             up += ls[i];
    73             update(num[i]);
    74         }
    75 
    76         memset(bit, 0, sizeof(bit));
    77         for(int i = n; i >= 1; i--) {
    78             rs[i] = query(num[i] - 1);
    79             rb[i] = query(m) - query(num[i]);
    80             down += rs[i];
    81             update(num[i]);
    82         }
    83 
    84         LL ans = 0;
    85 
    86         for(int i = 1; i <= n; i++) {
    87             ans -= ls[i] * lb[i];
    88             ans -= rs[i] * ls[i];
    89             ans -= rb[i] * lb[i];
    90             ans -= rb[i] * rs[i];
    91         }
    92 
    93         printf("%I64d
    ", up * down + ans);
    94     }
    95     return 0;
    96 }
  • 相关阅读:
    dispatchEvent 的应用
    sql语句中日期时间格式化查询
    Dotfuscator Professional Edition 4.9.7500.9484 混淆工具破解版+使用教程
    多表链接 Left join
    多线程计时器
    C#数据库事务原理及实践
    用户sa 登录失败。原因: 该帐户的密码必须更改 sql2008
    Application.DoEvents()和多线程
    C#中DataSet和DataReader的区别
    ROW_NUMBER() OVER函数的基本用法
  • 原文地址:https://www.cnblogs.com/fightfordream/p/5733905.html
Copyright © 2020-2023  润新知