bzoj3295 CQOI2011 動態逆序對

2021-07-11 19:26:49 字數 1407 閱讀 5411

time limit: 10 sec  

memory limit: 128 mb

submit: 3122  

solved: 986 [

submit][

status][

discuss]

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

>aj

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

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

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

5 415

3425

1425

221樣例解釋

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

n<=100000 m<=50000

方法一:各種

樹套樹,目測**難度較大

方法二:

cdq分治

+樹狀陣列

將刪除操作逆向,轉化成新增操作。

於是問題轉化成每次向序列中新增乙個數,詢問逆序對數。

考慮每次加入乙個數對答案的影響,它會與前面並且大於它的數和後面並且小於它的數構成逆序對。

然後在cdq分治裡做兩次就可以了。

#include#include#include#include#include#include#define f(i,j,n) for(int i=j;i<=n;i++)

#define d(i,j,n) for(int i=j;i>=n;i--)

#define ll long long

#define maxn 100005

using namespace std;

int n,m,pos[maxn],c[maxn],sl[maxn],sr[maxn];

ll ans[maxn];

struct dataa[maxn],b[maxn];

inline int read()

while (ch>='0'&&ch<='9')

return x*f;

}inline void add(int x,int y)

inline int query(int x)

inline void cdq(int l,int r)

f(i,l,r) a[i]=b[i];

tmp=l;

f(i,mid+1,r)

f(i,tmp+1,mid) add(a[i].v,-1);

cdq(l,mid);cdq(mid+1,r);

}int main()

Cqoi2011 BZOJ3295 動態逆序對

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

bzoj3295 Cqoi2011 動態逆序對

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

bzoj3295 Cqoi2011 動態逆序對

對於序列a,它的逆序對數定義為滿足 i j,且a i a j的數對 i,j 的個數。給1到 n的乙個排列,按照某種順序依次刪除 m個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。輸入第一行包含兩個整數 n和m,即初始元素的個數和刪除的元素個數。以下 n行每行包含乙個1到 n之間的正整...