bzoj 3289 Mato的檔案管理

2021-08-16 01:35:18 字數 1526 閱讀 4953

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

這道題第一眼看上去是一臉懵逼,仔細想一想後,如果我們知道[l,r]的答案,那其實我們就可以知道[l,r-1],[l,r+1],[l+1,r],[l-1,r]的答案。於是乎,便想到了莫隊。轉化過程略過,自己推。

但求乙個區間<=x的個數(用log的時間),這個問題呢一開始沒想到,之後才想到可以用樹狀陣列,那麼這道題就解決了。

#include

#include

#include

#include

#include

using namespace std;

struct node

q[51000],b[51000];

int n,m;

int a[51000],belong[51000],bl[51000],br[51000],t[51000];

int lowbit(int

x)void add(int

x,int w)

int getsum(int

x)void fk()

br[belong[n]]=n;

}bool cmp1(node a,node b)

if(belong[a.l]>belong[b.l])return false;

else

return true;

}bool cmp2(node a,node b)

bool c***(node a,node b)

int ans;

void solve()

for(int j=r+1;j<=q[i].r;j++)

for(int j=l;j<=q[i].l-1;j++)

for(int j=l-1;j>=q[i].l;j--)

l=q[i].l,r=q[i].r;

q[i].s=ans;

}}int main()

sort(b+1,b+n+1,c***);

for(int i=1;i<=n;i++)a[b[i].id]=i;

scanf("%d",&m);

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

fk();

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

solve();

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

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

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有乙個習慣,他...