zoukankan      html  css  js  c++  java
  • BZOJ 3289:Mato的文件管理(莫队算法+树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3289

    题意:……

    思路:求交换次数即求逆序对数。确定了这个之后,先离散化数组。然后在后面插入元素的话,就是在区间里面找比它大的元素数量,在前面插入元素的话,就是在区间里面找比它小的元素数量。删除操作类似。因为排序是从小到大排序,所以要找比它大的数量就是区间长度减去小于等于该元素的数量,所以是(R - L + 1 - sum(a[i])),要找比它小的数量就是(sum(a[i] - 1))。然后用莫队算法处理区间询问就好了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cmath>
     5 using namespace std;
     6 #define N 50010
     7 struct node {
     8     int l, r, id, ans;
     9 } p[N];
    10 int bit[N], a[N], b[N], num[N], ans, kuai, n;
    11 
    12 bool cmp(const node &a, const node &b) {
    13     if(a.l / kuai == b.l / kuai) return a.r < b.r;
    14     return a.l / kuai < b.l / kuai;
    15 }
    16 bool cmpid(const node &a, const node &b) { return a.id < b.id; }
    17 int lowbit(int x) { return x & (-x); }
    18 void add(int x, int w) { for( ; x <= n; x += lowbit(x)) bit[x] += w; }
    19 int sum(int x) { int ans = 0; for( ; x ; x -= lowbit(x)) ans += bit[x]; return ans; }
    20 
    21 int main() {
    22     while(~scanf("%d", &n)) {
    23         for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
    24         int q; scanf("%d", &q);
    25         for(int i = 1; i <= q; i++) scanf("%d%d", &p[i].l, &p[i].r), p[i].id = i;
    26 
    27         memset(bit, 0, sizeof(bit));
    28         ans = 0; kuai = sqrt(n);
    29         sort(b + 1, b + 1 + n);
    30         int cnt = unique(b + 1, b + 1 + n) - b - 1;
    31         for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;
    32 
    33         sort(p + 1, p + 1 + q, cmp);
    34         for(int L = 1, R = 0, i = 1; i <= q; i++) {
    35             int l = p[i].l, r = p[i].r;
    36             for( ; L < l; L++) { ans -= sum(a[L] - 1); add(a[L], -1); }
    37             for( ; L > l; L--) { ans += sum(a[L-1] - 1); add(a[L-1], 1); }
    38             for( ; R < r; R++) { ans += R - L + 1 - sum(a[R+1]); add(a[R+1], 1); }
    39             for( ; R > r; R--) { ans -= R - L + 1 - sum(a[R]); add(a[R], -1); }
    40             p[i].ans = ans;
    41         }
    42         sort(p + 1, p + 1 + q, cmpid);
    43         for(int i = 1; i <= q; i++) printf("%d
    ", p[i].ans);
    44     }
    45     return 0;
    46 }
  • 相关阅读:
    mint18
    ubuntu 安装mysql
    Linux awk 命令 说明
    shell EOF
    linux下使用lftp的小结
    MySQL的mysqldump工具的基本用法
    linux shell中 if else以及大于、小于、等于逻辑表达式介绍
    MySQL日期数据类型、时间类型使用总结
    linux 修改系统字符集,查看字符
    ORACLE基本用法及常用命令
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6350335.html
Copyright © 2011-2022 走看看