1. 程式人生 > >luogu P1393 & P3157 動態逆序對

luogu P1393 & P3157 動態逆序對

傳送門

另一個在推薦的相關題目裡有

刪除不好刪 反過來變成加 都是基本操作

然後被刪的數加一維就是時間 

然後時間第一維 序號第二維 權值第三維

開一個權值樹狀陣列維護三維偏序就行

兩個題要注意輸入的時候一個是刪掉的權值 一個是刪掉的編號

然後如果開不下要離散化

Code:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #define rep(i,a,n) for(int i = a;i <= n;++i)
 6
#define per(i,n,a) for(int i = n;i >= a;--i) 7 using namespace std; 8 typedef long long ll; 9 ll read() { 10 ll as = 0,fu = 1; 11 char c = getchar(); 12 while(c < '0' || c > '9') { 13 if(c == '-') fu = -1; 14 c = getchar(); 15 } 16 while(c >= '0' && c <= '
9') { 17 as = as * 10 + c - '0'; 18 c = getchar(); 19 } 20 // printf("#%d\n",as); 21 return as * fu; 22 } 23 const int N = 100005; 24 //head 25 int n,Q; 26 struct node { 27 int x,idx,tim; 28 bool operator < (const node &o) const { 29 return tim < o.tim || (tim == o.tim && idx < o.idx);
30 } 31 } a[N],tmp[N]; 32 int b[N],ans[N]; 33 34 int t[N]; 35 void upd(int x,int k) { 36 for(int i = x;i <= n;i += (i & (-i))) t[i] += k; 37 } 38 int qry(int x) { 39 int sum = 0; 40 for(int i = x;i;i -= (i & (-i))) sum += t[i]; 41 return sum; 42 } 43 44 45 void CDQ(int l,int r) { 46 if(l == r) return; 47 int m = l+r >> 1,p1,p2; 48 CDQ(l,m),CDQ(m+1,r); 49 50 p1 = l,p2 = m+1; 51 rep(i,l,r) { 52 if(p1 <= m && (p2 > r || a[p1].idx < a[p2].idx)) 53 tmp[i] = a[p1],upd(a[p1].x,1),p1++; 54 else tmp[i] = a[p2],ans[tmp[i].tim] += qry(n) - qry(a[p2].x),p2++; 55 } 56 rep(i,l,m) upd(a[i].x,-1); 57 58 p1 = m,p2 = r; 59 rep(i,l,r) { 60 if(p1 >= l && (p2 == m || (a[p1].idx > a[p2].idx))) 61 upd(a[p1].x,1),p1--; 62 else ans[a[p2].tim] += qry(a[p2].x-1),p2--; 63 } 64 rep(i,l,m) upd(a[i].x,-1); 65 66 rep(i,l,r) a[i] = tmp[i]; 67 } 68 69 int main() { 70 n = read(),Q = read(); 71 rep(i,1,n) { 72 a[i].x = read(); 73 a[i].idx = b[a[i].x] = i; 74 a[i].tim = 1; 75 } 76 rep(i,1,Q) a[b[read()]].tim = n-i+1; 77 sort(a+1,a+n+1),CDQ(1,n); 78 int tot = 0; 79 rep(i,1,n) tot += ans[i]; 80 per(i,n,n - Q + 1) printf("%lld\n",tot),tot -= ans[i]; 81 return 0; 82 }