傳送門
設 $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 對答案產生的影響,拿下面的...