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這天需要交換的次數。
hint
n,q <= 50000
樣例解釋:第一天,mato不需要交換
第二天,mato可以把2號交換2次移到最後。
本題是莫隊加線段樹或樹狀陣列,,然而樹狀陣列不是太會用。。雖然線段樹會比較麻煩。
很顯然,本題要求最少的交換次數,那麼每存在乙個逆序對,就需要交換至少一次交換使它們的有序,也可以驗證逆序對數就等於最少交換次數,因為若是第1,3個數為逆序對,那麼有一種情況是第二個數比第乙個小且比第三個大,那麼此時逆序對數為3,先將1,2換位,然後第2,3個數換位,然後換1,2個數,此時數列有序。其餘情況也可驗證,多個數情況相同。
維護的話用線段樹即可。用權值線段樹維護當前區間[l,r],每加入乙個數就加上當前線段樹中與他構成逆序對的數的個數,加入答案即可。在構造線段樹時注意離散化。
**如下:
#include
#include
#include
#include
#define n 50010
using namespace std;
struct tree }node[n*3];
struct question }q[n];
int num[n],s[n],head=1,n,m;
int cmp(question a,question b) return;
}int find(int
x,int d) return ans;
}void work() for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}int in()
int main()
sort(q+1,q+m+1,cmp); work();
}
bzoj3289 Mato的檔案管理
給定乙個序列,每次詢問乙個區間,你可以交換相鄰兩個元素,這個區間你最少需要多少次交換才能使其有序。我們觀察,每次交換如果交換a i 和a i 1 那麼顯然a i a i 1 交換後逆序對個數減一。當序列逆序對個數為0時序列就有序。那麼顯然題意就是詢問區間逆序對個數。我們可以用莫隊演算法來做。因為它符...
bzoj3289 Mato的檔案管理
description mato同學從各路神犇以各種方式 你們懂的 收集了許多資料,這些資料一共有n份,每份有乙個大小和乙個編號。為了防止他人偷拷,這些資料都是加密過的,只能用mato自己寫的程式才能訪問。mato每天隨機選乙個區間 l,r 他今天就看編號在此區間內的這些資料。mato有乙個習慣,他...
bzoj 3289 Mato的檔案管理
mato同學從各路神犇以各種方式 你們懂的 收集了許多資料,這些資料一共有n份,每份有乙個大小和乙個編號。為了防止他人偷拷,這些資料都是加密過的,只能用mato自己寫的程式才能訪問。mato每天隨機選乙個區間 l,r 他今天就看編號在此區間內的這些資料。mato有乙個習慣,他總是從檔案大小從小到大看...