P3157 CQOI2011 動態逆序對

2022-05-19 11:43:19 字數 1596 閱讀 3346

傳送門

設 $val[i]$ 為位置 $i$ 的值

維護 $ansl[i]$ 表示位置 $i$ 的數左邊所有大於 $val[i]$ 的數的數量

維護 $ansr[i]$ 表示位置 $i$ 的數右邊所有小於 $val[i]$ 的數的數量

考慮先求出一開始總的逆序對數 $ans$

每次刪除乙個數 (位置為 $p$ ) 就把 $ans$ 減去 $ansl[p]+ansr[p]$

但是這樣會多減,因為有些數在更之前就刪掉了

考慮維護這些刪掉的數的貢獻,發現那麼我們的 $ans$ 多扣了以後還要加上之前刪除的位置小於 $p$ 且大於 $val[p]$ 的數以及位置大於 $p$ 且小於 $val[p]$ 的數

因為每次刪掉相當於單點修改,查詢就是區間查詢,所以考慮用樹狀陣列套動態開點權值線段樹來維護

具體看**

#include#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;inline

intread()

while(ch>='

0'&&ch<='

9')

return x*f;

}const

int n=2e5+7,m=3e7+7

;int

n,m;

int t[n];//

這個樹狀陣列維護ansl,ansr和ans

inline void t_add(int x,int y)

inline

int t_sum(int x)

int rt[n],s[m],l[m],r[m],cnt;//

樹狀陣列套動態開點的權值線段樹

intpos,ql,qr,res,pd;

inline

void s_ins(int &o,int l,int r)//

往線段樹插入乙個數

inline

void s_query(int o,int l,int r)//

//pd判斷是+還是-

int mid=l+r>>1

; s_query(l[o],l,mid); s_query(r[o],mid+1

,r);

}inline

int query(int pl,int pr,int vl,int vr)//

查詢當前位置》=pl,<=pr,權值》=vl,<=vr的數的數量

intansl[n],ansr[n];

ll ans;

intval[n],id[n];

intmain()

for(int i=1;i<=n;i++) t[i]=0

;

for(int i=n;i;i--) ansr[i]=t_sum(val[i]-1),t_add(val[i],1

);

inta,p;

while(m--)

return0;

}

P3157 CQOI2011 動態逆序對

題目描述 現在給出 1 n 的乙個排列,按照某種順序依次刪除 m 個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。輸入格式 第一行包含兩個整數 n和 m,即初始元素的個數和刪除的元素個數。以下 n 行,每行包含乙個 1 n 之間的正整數,即初始排列。接下來 m 行,每行乙個正整數,依...

P3157 CQOI2011 動態逆序對

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

洛谷 P3157 CQOI2011 動態逆序對

對於序列a,它的逆序對數定義為滿足iaj的數對 i,j 的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。可以值域分塊,塊套樹狀陣列,樹套樹 不過用序列分塊 vector 一樣能水過這道題 考慮刪去乙個點 x 對答案產生的影響,拿下面的...