• Hdu 1394 【线段树 基础 求逆序数】.cpp


    题意:

      给出n个数..问循环排序后的最小逆序数

     

    思路:

      根据出现次序..用线段树的sum记录某一区间出现次数..

         把出现的数值a[i] 更新到 sum[a[i]]..

         根据题意..当每一次更新的之前..都对当前位置到最后位置出现的数进行查询..

      即可得到出现比该值早而又比该值大的数的个数..即满足逆序数对的定义..

         所以求和就可得到逆序数对的值..

     

       当每一次把队头的值移到队尾..

      逆序数对就减少了当前值(a[i]-1)<逆序数对包含该值的都没有了..>..

         但是还有一些逆序数对增加了..(加入到队尾时可与该数组成逆序数对的..)即n-a[i]对..

         所以每一次循环后存在的逆序数对个数就是:sum = sum-(a[i]-1) + (n-a[i]);

    Tips:

        暴力超时了..所以用线段树来算..

     

    Code:

    View Code
      1 #include <stdio.h>
      2 #include <cstring>
      3 #include <algorithm>
      4 using namespace std;
      5 
      6 const int MAXN = 5010;
      7 int sum[MAXN<<2];
      8 int a[MAXN];
      9 
     10 void pushup(int rt)
     11 {
     12     sum[rt] = sum[rt<<1] + sum[rt<<1|1];
     13 }
     14 
     15 void creat(int l, int r, int rt)
     16 {
     17     sum[rt] = 0;
     18     if(l == r)
     19         return;
     20     int mid = (l+r)>>1;
     21     creat(l, mid, rt<<1);
     22     creat(mid+1, r, rt<<1|1);
     23     pushup(rt);
     24 }
     25 
     26 void modify(int p,int l, int r, int rt)
     27 {
     28     if(l == r) {
     29         sum[rt]++;
     30         return;
     31     }
     32     int mid = (l+r)>>1;
     33     if(p <= mid) modify(p, l, mid, rt<<1);
     34     else modify(p, mid+1, r, rt<<1|1);
     35     pushup(rt);
     36 }
     37 
     38 int query(int l, int r, int L, int R, int rt)
     39 {
     40     if(l <= L && R <= r) {
     41         return sum[rt];
     42     }
     43     int mid = (L+R)>>1;
     44     int res = 0;
     45     if(l <= mid) res += query(l, r, L, mid, rt<<1);
     46     if(r > mid) res += query(l, r, mid+1, R, rt<<1|1);
     47     return res;
     48 }
     49 
     50 int main()
     51 {
     52     int i, j, k;
     53     int n, sum;
     54     while(scanf("%d", &n) != EOF)
     55     {
     56         int s = 0;
     57         creat(1, n, 1);
     58 
     59         for(i = 0; i < n; ++i) {
     60             scanf("%d", &a[i]);
     61             a[i]++;
     62             s += query(a[i], n, 1, n, 1);
     63             modify(a[i], 1, n, 1);
     64         }
     65 
     66         int mi = 0x1f1f1f1f;///!!!
     67         for(i = 0; i < n; ++i) {
     68             s = s-(a[i] - 1)+(n-a[i]);
     69             mi = min(mi, s);
     70         }
     71 
     72         printf("%d\n", mi);
     73     }
     74     return 0;
     75 }
     76 
     77 /*
     78 int main()
     79 {
     80     int i, j, k;
     81     int n;
     82     while(scanf("%d", &n) != EOF)
     83     {
     84         for(i = 0; i < n; ++i) {
     85             scanf("%d", &a[i]);
     86         }
     87 
     88         int mi = 0x1f1f1f1f, s = 0;
     89         for(i = 0; i < n; ++i) {
     90             creat(1, n, 1);
     91             s = 0;
     92             for(j = 0; j < n; ++j) {
     93                 s += query(a[(i+j)%n]+1, n, 1, n, 1);
     94                 modify(a[(j+i)%n]+1, 1, n, 1);
     95             }
     96             mi = min(mi, s);
     97         }
     98 
     99         printf("%d\n", mi);
    100     }
    101     return 0;
    102 }
    103 */

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394

  • 相关阅读:
    python依赖包整体迁移方法
    ubuntu关于ssh协议登录问题
    k8s部署02-----kubeadm部署k8s
    k8s部署01-----what is k8s?
    兼容到ie10的js文件导出、下载到本地
    webstorm减少内存占用
    foxmail占cpu 100%解决办法
    原生js返回顶部
    js字符串驼峰和下划线互相转换
    element-ui的rules中正则表达式
  • 原文地址:https://www.cnblogs.com/Griselda/p/2719083.html
Copyright © 2020-2023  润新知