題解 bzoj3289 Mato的檔案管理

2021-08-06 02:43:18 字數 1483 閱讀 9479

mato同學從各路神犇以各種方式(你們懂的)收集了許多資料,這些資料一共有n份,每份有乙個大小和乙個編號。為了防止他人偷拷,這些資料都是加密過的,只能用mato自己寫的程式才能訪問。mato每天隨機選乙個區間[l,r],他今天就看編號在此區間內的這些資料。mato有乙個習慣,他總是從檔案大小從小到大看資料。他先把要看的檔案按編號順序依次拷貝出來,再用他寫的排序程式給檔案大小排序。排序程式可以在1單位時間內交換2個相鄰的檔案(因為加密需要,不能隨機訪問)。mato想要使檔案交換次數最小,你能告訴他每天需要交換多少次嗎?

第一行乙個正整數n,表示mato的資料份數。

第二行由空格隔開的n個正整數,第i個表示編號為i的資料的大小。

第三行乙個正整數q,表示mato會看幾天資料。

之後q行每行兩個正整數l、r,表示mato這天看[l,r]區間的檔案。

q行,每行乙個正整數,表示mato這天需要交換的次數。

4 1 4 2 3

2 1 2

2 40

2此題就是求區間逆序對數量。莫隊,用樹狀陣列o(

log2

n)轉移,就是查詢區間新加的那個數(或者減少的那個數)在區間內貢獻的逆序對數量。

複雜度o(n

n√lo

g2n)

。**:

#include

#include

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int maxn=50010;

struct qq[maxn];

int b,block[maxn],n,m,cnt,a[maxn],rnk[maxn];

ll ans;

struct bit

void add(int x,int val)

ll query(int x)

}bit;

bool comp(q x,q y)

int main()

sort(rnk+1,rnk+n+1);

cnt=unique(rnk+1,rnk+n+1)-rnk-1;

for(int i=1;i<=n;i++)a[i]=lower_bound(rnk+1,rnk+cnt+1,a[i])-rnk;

scanf("%d",&m);

for(int i=1;i<=m;i++)

scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;

sort(q+1,q+m+1,comp);

for(int i=1,l=1,r=0;i<=m;i++);

sort(q+1,q+m+1,comp_id);

for(int i=1;i<=m;i++)printf("%lld\n",q[i].a);

return

0;}

bzoj3289 Mato的檔案管理

給定乙個序列,每次詢問乙個區間,你可以交換相鄰兩個元素,這個區間你最少需要多少次交換才能使其有序。我們觀察,每次交換如果交換a i 和a i 1 那麼顯然a i a i 1 交換後逆序對個數減一。當序列逆序對個數為0時序列就有序。那麼顯然題意就是詢問區間逆序對個數。我們可以用莫隊演算法來做。因為它符...

bzoj 3289 Mato的檔案管理

description mato同學從各路神犇以各種方式 你們懂的 收集了許多資料,這些資料一共有n份,每份有乙個大小和乙個編號。為了防止他人偷拷,這些資料都是加密過的,只能用mato自己寫的程式才能訪問。mato每天隨機選乙個區間 l,r 他今天就看編號在此區間內的這些資料。mato有乙個習慣,他...

bzoj3289 Mato的檔案管理

description mato同學從各路神犇以各種方式 你們懂的 收集了許多資料,這些資料一共有n份,每份有乙個大小和乙個編號。為了防止他人偷拷,這些資料都是加密過的,只能用mato自己寫的程式才能訪問。mato每天隨機選乙個區間 l,r 他今天就看編號在此區間內的這些資料。mato有乙個習慣,他...