BZOJ3295 Cqoi2011 動態逆序對

2022-05-08 05:27:07 字數 2140 閱讀 5400

對於序列a,它的逆序對數定義為滿足i

>aj

的數對(i,j)的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。

輸入第一行包含兩個整數n和m,即初始元素的個數和刪除的元素個數。以下n行每行包含乙個1到n之間的正整數,即初始排列。以下m行每行乙個正整數,依次為每次刪除的元素。

輸出包含m行,依次為刪除每個元素之前,逆序對的個數。

5 4153

4251

4252

21樣例解釋

(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。

n<=100000 m<=50000

正解:cdq分治

解題報告:

cdq分治裸題。其實也是樹套樹裸題,那麼拿來當cdq練手吧。

考慮把刪除變成倒著插入,那麼我給每個座標乙個權值t,表示插入時間。那麼第乙個刪除的t座標當然是n,表示最後乙個插入。然後為了方便,我們把未被刪除的結點的t座標從左往右設為1、2、3...

考慮問題轉換成了求對於(t0,x0,y0)滿足ty0的(t,x,y)的個數,這樣就變成了三維偏序的裸題了。細節上有必要再說一下:

首先cdq分治之前按t排序,保證t已經有序,在每次分治內部,按x排序,正著掃整個區間的時候,對於[mid+1,r]的區間就在樹狀陣列上查詢大於他的y的值的數量;倒著掃,對於[mid+1,r]的區間就在樹狀陣列上查詢小於他的y的值的數量。因為左邊的所有元素對於右邊的所有元素而言,是可以肯定t要小一些的,所以cdq分治就可以巧妙地解決三維偏序的問題。之後在遞迴處理左邊右邊就可以了,同樣的做法。

ps:我開始t了兩發,犯的是寫cdq分治的常見錯誤,就是在分治裡面清空了陣列,事實上只要清除剛才打上去的標記就可以了,無需清空。

1

//it is made by ljh2000

2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include

13using

namespace

std;

14 typedef long

long

ll;15

const

int inf = (1

<<30

);16

const

int maxn = 100011;17

intn,m,c[maxn],match[maxn],ans[maxn];

18ll ans;

19struct

nodea[maxn],b[maxn];

23 inline bool cmpx(node q,node qq)

24 inline bool cmpt(node q,node qq)

25 inline void add(int x,int val)

26 inline int query(int x)

27 inline int

getint()

2833

34 inline void cdq(int l,int

r)42

for(int i=1;i<=size;i++) if(b[i].flag==0) add(b[i].y,-1

);43

for(int i=size;i>=1;i--)

47for(int i=1;i<=size;i++) if(b[i].flag==0) add(b[i].y,-1

);48 cdq(l,mid); if(mid1

,r);49}

5051 inline void

work() int cc=n,x;

53for(int i=1;i<=m;i++) for(int i=1;i<=n;i++) if(a[i].t==0) a[i].t=cc--;

54 sort(a+1,a+n+1,cmpt); cdq(1

,n);

55for(int i=1;i<=n;i++) ans+=ans[i];

56for(int i=n;i>n-m;i--) 60}

6162

intmain()

63

bzoj3295 CQOI2011 動態逆序對

time limit 10 sec memory limit 128 mb submit 3122 solved 986 submit status discuss 對於序列a,它的逆序對數定義為滿足i aj 的數對 i,j 的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次...

Cqoi2011 BZOJ3295 動態逆序對

對於序列a,它的逆序對數定義為滿足i 樹狀陣列 一看到逆序對就要想到樹狀陣列。維護每個數前面到目前有多少個比自己大。動態的思路 因為要動態維護,每次只刪掉乙個數在逆序對中的貢獻 及每個數前面有多少個比自己大,每個數後面有多少數比自己小。先預處理出每個數前面有多少個比自己大ll i 每個數後面有多少個...

bzoj3295 Cqoi2011 動態逆序對

傳送門 題解 cdq分治 我們仔細想一想維護逆序對的時候我們用的不就是歸併排序嗎?而歸併排序不就可以看作一種分治嗎?於是此題走上正軌,我們可以用分治來寫 怎麼寫?我們刪除乙個點,損失了什麼?1.這個點x之前比我大的個數記為big x 這個點x之後比我小的記作small x 那麼損失 small x ...