zoukankan      html  css  js  c++  java
  • hdu2838 cow sorting用树状数组求逆序对

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/2838/

    题目解法:题目给出一个1-n的排列,操作只有一种:交换相邻的元素,代价是两个元素之和,问将该序列变成升序排列的最小代价。就是要在线求解,每输入一个数a就要查询之前的数中有多少数比a大,这些数由于在a的前面,所以都会与a发生一次交换,否则a无法排在他们前面。假设a前面有k个数比a大,则代价之一是k*a。另一部分代价来自于交换这些数时前面的比a大的数的和。我们可以用树状数组高效的求出截止a位置的逆序对数量,并且可以用另一个树状数组维护比a小的数的和,这个操作很简单,只需要没次输入x时在x位置加上x就行,然后对a求前缀和就可得比a小的所有的数的和,由于所有的数都是小于等于n的,所以大于a的数的和是小于等于n的数的和减去小于等于x的数的和(容斥原理)。最后要注意的一点是要用long long整数。

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef unsigned int ui;
     4 typedef long long ll;
     5 typedef unsigned long long ull;
     6 #define pf printf
     7 #define mem(a,b) memset(a,b,sizeof(a))
     8 #define prime1 1e9+7
     9 #define prime2 1e9+9
    10 #define pi 3.14159265
    11 #define scand(x) scanf("%llf",&x) 
    12 #define f(i,a,b) for(int i=a;i<=b;i++)
    13 #define scan(a) scanf("%d",&a)
    14 #define dbg(args) cout<<#args<<":"<<args<<endl;
    15 #define pb(i) push_back(i)
    16 #define ppb(x) pop_back(x)
    17 #define inf 0x3f3f3f3f
    18 #define maxn 100010
    19 int n,m,t;
    20 ll sum[maxn],c[maxn];
    21 ll lowbit(ll x)
    22 {
    23     return x&(-x);
    24 }
    25 void update(int x,int y)
    26 {
    27     for(int i=x;i<=n;i+=lowbit(i))
    28     {
    29         c[i]+=y;//c[i]=1时表示插入数i 
    30         sum[i]+=x;//sum[i]:可以理解为在i位置上放i 
    31     }
    32 }
    33 ll query(int x)//求出小于等于x的所有数之和 
    34 {
    35     ll ans=0;
    36     for(int i=x;i;i-=lowbit(i))
    37     {
    38         ans    +=sum[i];
    39     }
    40     return ans;
    41 }
    42 ll query2(int x)//求出比x小的数的个数 
    43 {
    44     ll ans=0;
    45     for(int i=x;i;i-=lowbit(i))
    46     {
    47         ans+=c[i];
    48     }
    49     return ans;
    50 }
    51 int main()
    52 {
    53     //freopen("input.txt","r",stdin);
    54     //freopen("output.txt","w",stdout);
    55     std::ios::sync_with_stdio(false);
    56     scan(n);
    57     int x;
    58     ll ans=0 ;
    59     f(i,1,n)
    60     {
    61         scan(x);
    62         ll tmp=i-1-query2(x-1);//选出比x大的数的个数,tmp=0时表示i是当前最大的数,所以不需要 
    63         //dbg(tmp);
    64         if(tmp!=0)
    65         {
    66             ans+=tmp*x;
    67             ans+=query(n)-query(x);//选出比x大但是小于等于n的数(因为编号是连续的,所以最大是n) 
    68          } 
    69          update(x,1);
    70     }
    71     pf("%lld
    ",ans);
    72  } 
  • 相关阅读:
    ios des加密
    testng-注解之@BeforeGroups、@AfterGroups +分组测试
    testng -忽略测试
    testng -注解之@BeforeSuite、@AfterSuite
    jmeter创建测试计划,执行post请求
    jmeter进行压力测试
    jmeter在mac电脑上安装使用
    java -获取变量类型
    java中枚举类enum
    java的日期与时间,Date ,SImpleDateFormat(), Calendar
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12439216.html
Copyright © 2011-2022 走看看