BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

3289: Mato的文件管理

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 2399  Solved: 988
[Submit][Status][Discuss]

Description

Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号。为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问。Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料。Mato有一个习惯,他总是从文件大小从小到大看资料。他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序。排序程序可以在1单位时间内交换2个相邻的文件(因为加密需要,不能随机访问)。Mato想要使文件交换次数最小,你能告诉他每天需要交换多少次吗?

Input

第一行一个正整数n,表示Mato的资料份数。
第二行由空格隔开的n个正整数,第i个表示编号为i的资料的大小。
第三行一个正整数q,表示Mato会看几天资料。
之后q行每行两个正整数l、r,表示Mato这天看[l,r]区间的文件。

Output

q行,每行一个正整数,表示Mato这天需要交换的次数。

Sample Input

4
1 4 2 3
2
1 2
2 4

Sample Output

0
2

HINT

Hint

n,q <= 50000

样例解释:第一天,Mato不需要交换

第二天,Mato可以把2号交换2次移到最后。



普通莫队,区间转移时逆序对用树状数组处理 logn

树状数组求哪一块一定要想对了

//
//  main.cpp
//  分块1
//
//  Created by Candy on 2016/12/17.
//  Copyright © 2016年 Candy. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=5e4+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}
int n,Q,a[N],bl,pos[N],mp[N],m;
inline int Bin(int v){
    int l=1,r=m;
    while(l<=r){
        int mid=(l+r)>>1;
        if(mp[mid]==v) return mid;
        if(v<mp[mid]) r=mid-1;
        else l=mid+1;
    }
    return -1;
}
struct ques{
    int l,r,id;
    bool operator <(const ques a)const{
        if(pos[l]==pos[a.l]) return r<a.r;
        else return pos[l]<pos[a.l];
    }
}q[N];
int c[N];
ll ans,an[N];
inline int lowbit(int x){return x&-x;}
inline void add(int p,int v){for(int i=p;i<=n;i+=lowbit(i))c[i]+=v;}
inline int sum(int p){
    int res=0;
    for(int i=p;i;i-=lowbit(i)) res+=c[i];
    return res;
}
inline int sum(int l,int r){
    return sum(r)-sum(l-1);
}
void solve(){
    int l=1,r=0;
    for(int i=1;i<=Q;i++){
        while(r<q[i].r) r++,ans+=sum(a[r]+1,m),add(a[r],1);
        while(r>q[i].r) ans-=sum(a[r]+1,m),add(a[r],-1),r--;
        while(l<q[i].l) ans-=sum(1,a[l]-1),add(a[l],-1),l++;
        while(l>q[i].l) l--,ans+=sum(1,a[l]-1),add(a[l],1);
        an[q[i].id]=ans;
    }
}
int main(int argc, const char * argv[]) {
    n=read();
    bl=sqrt(n);
    for(int i=1;i<=n;i++) a[i]=mp[i]=read(),pos[i]=(i-1)/bl+1;
    sort(mp+1,mp+1+n);
    m=1;
    for(int i=2;i<=n;i++) if(a[i]!=a[i-1]) a[++m]=a[i];
    for(int i=1;i<=n;i++) a[i]=Bin(a[i]);

    Q=read();
    for(int i=1;i<=Q;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
    sort(q+1,q+1+Q);
    solve();
    for(int i=1;i<=Q;i++) printf("%lld\n",an[i]);
    return 0;
}
时间: 2024-11-10 05:41:51

BZOJ 3289: Mato的文件管理[莫队算法 树状数组]的相关文章

【BZOJ3289】Mato的文件管理 莫队算法+树状数组

[BZOJ3289]Mato的文件管理 Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排序程序可以在1单位时间内交换2个相邻的文件(因为加密

bzoj 3289: Mato的文件管理 莫队+线段树

题目链接 给一些询问,每个询问给出区间[L, R] , 求这段区间的逆序数. 先分块排序, 然后对于每次更改, 如果是更改L, 那么应该查询区间内比他小的数的个数, 如果更改R, 查区间内比他大的数的个数. 记得离散化. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_pair(x, y) 6

【bzoj3289】Mato的文件管理 离散化+莫队算法+树状数组

原文地址:http://www.cnblogs.com/GXZlegend/p/6805224.html 题目描述 Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排

BZOJ 3289:Mato的文件管理(莫队算法+树状数组)

http://www.lydsy.com/JudgeOnline/problem.php?id=3289 题意:…… 思路:求交换次数即求逆序对数.确定了这个之后,先离散化数组.然后在后面插入元素的话,就是在区间里面找比它大的元素数量,在前面插入元素的话,就是在区间里面找比它小的元素数量.删除操作类似.因为排序是从小到大排序,所以要找比它大的数量就是区间长度减去小于等于该元素的数量,所以是(R - L + 1 - sum(a[i])),要找比它小的数量就是(sum(a[i] - 1)).然后用莫

【BZOJ】3289: Mato的文件管理(莫队算法+树状数组)

http://www.lydsy.com/JudgeOnline/problem.php?id=3289 很裸的莫队... 离线了区间然后分块排序后,询问时搞搞就行了. 本题中,如果知道$[l, r]$后,考虑如何转移$[l, r+1]$,发现就是$a[r+1]$的颜色在这个区间的排名,然后$r-l+1-排名$就是需要移动的次数. 那么本题中因为只需要裸的排名,所以可以考虑用bit,即离散后搞. 然后就行了 #include <cstdio> #include <cstdio> #

bzoj 3289: Mato的文件管理 莫队+树状数组

3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先

HDU 6278 - Just h-index - [莫队算法+树状数组+二分][2018JSCPC江苏省赛C题]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6278 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others) Problem Description The h-index of an author is the largest h where he has at least h papers with citations not les

BZOJ 2120: 数颜色 带修改的莫队算法 树状数组套主席树

https://www.lydsy.com/JudgeOnline/problem.php?id=2120 标题里是两种不同的解法. 带修改的莫队和普通莫队比多了个修改操作,影响不大,但是注意一下细节不要出现zz错误. 这道题修改的数量比较少可以写莫队,但是如果修改数量多或者是特别极限的数据大概是不行的吧. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstrin

[bzoj3289]Mato的文件管理_莫队_树状数组

Mato的文件管理 bzoj-3289 题目大意:给定一个n个数的序列.m次询问:一段区间中的逆序对个数. 注释:$1\le n\,mle 5\cdot 10^4$. 想法: 开始想这个题的大佬们,给您点儿提示吧:$O(nlogn\sqrt(n))$可过哦! 所以这个题就是莫队的裸题了. 我们的莫队上的区间在动的时候随时更新树状数组上的信息即可.. 然后碰见了一整块区间,我们就直接求逆序对即可, 最后,附上丑陋的代码... ... #include <iostream> #include &l