【問題描述】
對於序列a,它的逆序對數定義為滿足i<j,且ai>aj的數對(i,j)的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每次刪除乙個元素之前統計整個序列的逆序對數。
【輸入格式】
輸入第一行包含兩個整數n和m,即初始元素的個數和刪除的元素個數。
以下n行每行包含乙個1到n之間的正整數,即初始排列。以下m行每行乙個正整數,依次為每次刪除的元素。
【輸出格式】
輸出包含m行,依次為刪除每個元素之前,逆序對的個數。
【輸入樣例】
5 4
1 5
3 4
2 5
1 4 2
【輸出樣例】
5 2 2 1
【樣例解釋】
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
【資料規模】
n<=100000 , m<=50000
正解:cdq分治
解題報告:這個題是讓我們邊修改邊求逆序對,我們可以先離線處理,把刪除改成插入,然後序列中所有的逆序對應該滿足三個條件,我們用三個字母表示,t表示插入時間,x表示位置,y表示值,然後每一對逆序對應該是t【j】y【i】) 或 (x【j】>x【i】 && y【j】
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include8 #include 9
#define file(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
10#define rg register
11#define ll long long
12const
int n = 105000;13
14using
namespace
std;
1516
intgi()
20return
x;21}22
23struct
dated[n],a[n],b[n];
2627
intf[n],q[n],id[n],y[n],n,m,ans[n];
28bool
vis[n];
29void update(int x,int s)return
;}30
int query(int x)return
s;}31
32void cdq(int l,int
r)42
for (i=l; i1
);43
for (i=r,j=mid; i>mid; i--)
47for (i=mid; i>j; i--) update(d[i].s,-1
);48
int a1=0,b1=0;49
for (i=l; i<=mid; i++) a[++a1]=d[i];
50for (i=mid+1; i<=r; i++) b[++b1]=d[i];
51 i=1,j=1,k=l;
52while(i<=a1 && j<=b1) if (a[i].x];
53else d[k++]=b[j++];
54while(i<=a1) d[k++]=a[i++];
55while(j<=b1) d[k++]=b[j++];
56return;57
}5859int
main();
65for (i=m; i>=1; i--) d[t++]=(date);
66 cdq(1
,n);
67 ll sum=0;68
for (i=1; i<=n; i++) sum+=ans[i];
69for (i=1; i<=m; i++) printf("
%lld\n
",sum),sum-=ans[id[q[i]]];
70return0;
71 }
bzoj3295 動態逆序對
portal bzoj3295 雖然說這個可能原本是一道愉快的樹套樹但是 看到 按照某個順序依次刪除 這樣的字眼,比較容易聯想到乙個套路 反過來看,變成按照某個順序依次插入 那麼對於乙個詢問,刪掉它之前 化完了之後就是插入它之後 的所會影響到的逆序對數可以分為兩種 一種是在它前面但是比它大的,一種是...
bzoj3295 動態逆序對(CDQ分治)
time limit 10 sec memory limit 128 mb submit 7178 solved 2548 submit status discuss 對於序列a,它的逆序對數定義為滿足iaj的數對 i,j 的個數。給1到n的乙個排列,按照某種順序依次刪 除m個元素,你的任務是在每次...
BZOJ3295 動態逆序對(樹狀陣列套線段樹)
time limit 10 sec memory limit 128 mb submit 6058 solved 2117 submit status discuss 對於序列a,它的逆序對數定義為滿足i aj 的數對 i,j 的個數。給1到n的乙個排列,按照某種順序依次刪除m個元素,你的任務是在每...