題目如下
第三題:lyp 的密碼(lyp)
【題目描述】
眾所周知,lyp 喜歡以用各種方式折磨別人為樂,這次,他趁 wars 不在時在他的電腦上
掛了一把神奇的鎖,這把鎖需要一串巨長無比的數字密碼才可以解開,這 個密碼由 lyp 自
己保管,這樣 wars 就沒法 kingdom rush 了。但 wars 設法從 lyp 的腦袋中挖出了有關密碼
的資訊,這些資訊是一列非負整數。而解開密 碼鎖的方式是首先輸入這列這數的逆序
對數,而後依次會在 wars 的電腦螢幕上顯示兩個數字 p,q,你則需要輸入將整數列中第 p 個
整數替換成 q 後整個數列的逆序 對數,這樣的詢問會有 m 個。當然,這樣的替換只對這一
次的詢問有效。現在 wars 急著去打 kingdom rush,因此將開啟電腦的任務交給了你。
【輸入資料】
第 1 行 : n, m 以空格隔開
第 2 行 : n 個整數,以空格隔開,第 i 個整數代表 ai
第 3~m+2 行 : p, q 以空格隔開
【輸出資料】
依次輸出可以解開密碼鎖的整數列
【輸入樣例】
5 3
2 3 1 4 5
3 4
2 1
5 1
【輸出樣例】
2 0
2 5
【資料約定】
n<=50000,m<=50000
0<=序列的每一元素(包括詢問中的)<=100000
保證詢問合法。
易知此題為求逆序對數目+ 詢問每次在最初的數列修改1個值,求此時逆序對數目。
毫無疑問,一眼看此題就知道要寫線段樹。
因為此題資料範圍較大,那麼如何用線段樹以較好的時間複雜度去完成詢問操作才是此題難點。我在考場上啪啪啪瞬間敲完第一問之後問後就寫錯了,連線段樹都寫不出來真丟臉,搞得只能交裸,多虧主席後來一語點醒我的錯誤之處,orz。
至於此題建線段樹,是以數字大小為區間的,也即為[10, 20]的域記錄著數字大小在[10 , 20]的數字個數,與」星星」一題的建樹類似。
可以知道,如果真正按照此題要求去乙個乙個修改值的做是 tle 慘的,我的解決辦法是如下:(儘管貌似我跟其他人講我的方法他們都表示不理解= =)
我們先離線式的讀入所有詢問,每個詢問記好p、q、wh,p、q見題目描述,而wh則是詢問順序,然後先按p排序。(struct ask)
※實際上,每組詢問的解就是將原序列的逆序對數目– 與x[p]有關的逆序對數目 + 與q有關的逆序對數目。
設原序列為val[maxn],在插入v[i]進線段樹前,我們就可以查詢到目前樹中比val[i]要大的數字個數,也就是位於1~i - 1的數與x[i]組成的逆序對個數。且ask.p已經保證單增,則也可以處理出1~i - 1之前與ask.q組成的逆序對個數。
同樣的我們也要找出x[i]與ask.q與位於i + 1 ~ n的逆序對個數,那麼只需要把重新倒著建一遍線段樹即可,但要注意每次查詢就應該是查詢比val[i]與ask.q小的數字個數。
然後按照演算法輸出即可。
如還有不懂那肯定是對線段樹的觀念沒有轉換過來
看看我的**吧(遞迴版常數稍微大一點)歡迎提意見
#include #include #include #include #include #include #include using namespace std;
const int maxn = 50000 + 5;
const int limt = 100000 + 5;
struct node ask[maxn];
int n, m, tail, tot;
int trn[limt << 2], val[maxn], before[maxn];
bool _cmp_(node x, node y)
bool _cmp__(node x, node y)
bool _cmp___(node x, node y)
void pushup(int rt)
void buildtree(int l, int r, int rt)
int query(int x, int y, int l, int r, int rt)
void insert(int x, int l, int r, int rt)
int main()
cout << tot << endl;
memset(trn, 0, sizeof(trn));
sort(ask + 1, ask + m + 1, _cmp__); tail = 1;
for (int i = n; i >= 1; --i)
sort(ask + 1, ask + m + 1, _cmp___);
for (int i = 1; i <= m; ++i)
ask[i].ans = tot - before[ask[i].p] + ask[i].ans;
for (int i = 1; i <= m; ++i)
printf("%d\n", ask[i].ans);
return 0;
}
求逆序對數目
設計乙個平均時間為o n logn o nlogn o nlog n 的演算法,在n 1 n 1000 n 1 n 1000 n 1 n 1 000 個元素的陣列中尋找逆序對數目 這裡介紹分治的思想,用歸併對陣列進行排序,在排序的過程中,即可順便將逆序對數目求出來 首先,不斷地二分這個陣列,直到最小...
求逆序對數目
題目描述 給定乙個序列 a1,a2,a na 1,a 2,a n a1 a2 an 如果存在 a i aj a i a j ai aj 且 i i j 那麼我們稱之為逆序對的,求逆序對的數目。輸入第一行為 n nn,表示序列長度,接下來的 n nn 行,第 i 1 i 1i 1 行表示序列中的第 i...
分治法求逆序對數目
設a 1.n 是乙個包含n個不同整數的陣列。如果在ia j 則 i,j 就稱為a中的乙個逆序對 inversion 給出乙個演算法,確定n個元素的任何排列中逆序對的書目。時間複雜度為o nlgn 分治法求解思路 分解 將陣列a 1.n 分為兩個子串行a 1.p 和a p 1,n 二分法將其分解。解決...