對於每個「查詢」操作,其結果ans
[i]=
[1,i
−1
]ans[i] = [1,i-1]
ans[i]
=[1,
i−1]
中所有修改對其造成影響的疊加(這裡的「疊加」需要能夠比較方便的維護,例如sum
/min
/max
sum/min/max
sum/mi
n/ma
x等)定義s ol
ve(l
,r
)solve(l,r)
solve(
l,r)
為:對於第k
kk個操作,k∈[
l,r]
k∈[l,r]
k∈[l,r
],若其為查詢操作,則計算[l,
k−1]
[l,k-1]
[l,k−1
]中的修改對ans[i]造成的影響。設 mid
=(l+
r)/2
,sol
ve(l
,r
)mid = (l+r)/2,solve(l,r)
mid=(l
+r)/
2,so
lve(
l,r)
的執行步驟如下:
遞迴計算sol
ve(l
,mid
)solve(l,mid)
solve(
l,mi
d);計算[l,
mid]
[l,mid]
[l,mid
]中所有的修改對[mi
d+1,
r]
[mid+1,r]
[mid+1
,r]中所有查詢所造成的影響;
遞迴計算sol
ve(m
id+1
,r
)solve(mid+1,r)
solve(
mid+
1,r)
;一.
const
int n =
1e5+5;
int n , m, cnt;
ll val[n]
, ans[n]
, d[n]
;struct node qes[n <<1]
;void solve (
int l ,
int r)
}for
(int i =
1; i <= n ; i ++
) d[i]
+= d[i-1]
;for
(int i =
1; i <= n ; i ++
) d[i]
+= d[i-1]
;for
(int i = l ; i <= r ; i ++
) solve (mid +
1, r);}
intmain()
for(
int i = n +
1; i <= n + m ; i ++
) solve (
1, n + m)
;for
(int i =
1; i <= n + m ; i ++)if
(qes[i]
.op ==2)
cout << ans[i]
<< endl;
}
二.
解題思路:將逆序對問題轉換為修改和查詢操作之後然後進行cdq分治
const
int n =
5e5+5;
int n , m, cnt =0;
struct node q[n <<1]
, q1[n <<1]
;int ans[n]
;//op == 1 查詢
bool cmp (node a, node b)
void solve (
int l ,
int r)
for(
int i = l ; i <= r ; i ++
) q[i]
= q1[i]
; solve (mid +
1, r);}
intmain()
memcpy (q1, q,
sizeof
(q))
; solve (
1, cnt)
; ll ans =0;
for(
int i =
1; i <= cnt ; i ++
) ans +
= ans[i]
; cout << ans << endl;
}
CDQ分治學習筆記
今天學了一下cdq分治,感覺這東西真的挺好用的,趕緊寫點東西怕以後再忘咯 其實類似於cdq分治的東西在oi早期學排序的時候就應該學過,那就是歸併排序 歸併排序的原理和cdq分治大體一樣,先劃分成兩個區間,遞迴解決兩邊,再合併起來 並且用歸併排序求逆序對的時候本質上就是在解決乙個二維偏序的問題 首先回...
cdq分治學習筆記
0xff 學習cdq分治的前置知識 分治 歸併排序 分治 分治,字面上的解釋是 分而治之 就是把乙個複雜的問題分成兩個或更多的相同或相似的子問題,再把子問題分成更小的子問題 直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。度娘 歸併排序 歸併排序是普通分治的一種基本應用。將排序序列分...
CDQ分治學習筆記
cdq分治小結 cdq分治,同機房的大佬看了好幾天了,窩這種蒟蒻也來湊個熱鬧 qaq 引用大佬的話 二維裡面 最簡單的簡化版就是逆序對問題了,可以用樹狀陣列來維護,說他是簡化版其實是因為有一維 下標已經有序了,那麼就去大力 搞 另一維就好了 公升級版 一般的二維偏序問題 思路是一樣的,要通過排序使一...