📚【模板】CDQ分治
\(\textrm{luogu P3810 【模板】三维偏序(陌上花开)}\)
#include <stdio.h>
#include <bits/stl_algobase.h>
#include <bits/stl_algo.h>
const int N = 200010;
int n, m, k;
struct NODE {
int a, b, c;
int cnt, ans;
} node[N], use[N];
#define a(id) node[id].a
#define b(id) node[id].b
#define c(id) node[id].c
#define ua(id) use[id].a
#define ub(id) use[id].b
#define uc(id) use[id].c
bool comp1(NODE _x,NODE _y) {
return _x.a^_y.a ? _x.a < _y.a : _x.b^_y.b ? _x.b < _y.b : _x.c < _y.c;
}
bool comp2(const NODE &_x,const NODE &_y) {
return _x.b^_y.b ? _x.b < _y.b : _x.c < _y.c;
}
int tree[N];
void update(int pos,int val) {
for(;pos <= k;pos += (pos&(-pos)))
tree[pos] += val;
}
int query(int pos) {
int res = 0;
for(;pos;pos -= (pos&(-pos)))
res += tree[pos];
return res;
}
void cdq(int l,int r) {
if(l == r)
return;
int mid = (l+r)>>1;
cdq(l,mid);
cdq(mid+1,r);
std :: sort(use+l,use+mid+1,comp2);
std :: sort(use+mid+1,use+r+1,comp2);
int i, j;
for(i = mid+1, j = l;i <= r;++i) {
for(;ub(i) >= ub(j)&&j <= mid;++j)
update(uc(j),use[j].cnt);
use[i].ans += query(uc(i));
}
for(int i = l;i < j;++i)
update(uc(i),-use[i].cnt);
}
int res[N];
signed main() {
scanf("%d %d",&n,&k);
for(int i = 1;i <= n;++i)
scanf("%d %d %d",&a(i),&b(i),&c(i));
std :: sort(node+1,node+n+1,comp1);
for(int i = 1, j = 0;i <= n;++i) {
++j;
if(a(i)^a(i+1)||b(i)^b(i+1)||c(i)^c(i+1)) {
++m;
ua(m) = a(i);
ub(m) = b(i);
uc(m) = c(i);
use[m].cnt = j;
j = 0;
}
}
cdq(1,m);
for(int i = 1;i <= m;++i)
res[use[i].ans+use[i].cnt-1] += use[i].cnt;
for(int i = 0;i < n;++i)
printf("%d\n",res[i]);
}
\(\textrm{luogu P3157 [CQOI2011]动态逆序对}\)
#include <iostream>
#include <algorithm>
const int N = 1e5+10;
const int M = 5e4+10;
int n, m;
struct NODE {
int id, val;
int time;
int ans;
NODE ()
: id(0), val(0), time(1), ans(0) {}
} node[N];
int pos[N];
long long final_ans[M];
int tree[M];
void modify(int pos,int val) {
for(;pos <= m;pos += pos&-pos)
tree[pos] += val;
}
int query(int pos) {
int res = 0;
for(;pos;pos -= pos&-pos)
res += tree[pos];
return res;
}
void CDQ(int l,int r) {
if(l >= r)
return;
int mid = (l+r)>>1;
CDQ(l,mid);
CDQ(mid+1,r);
std :: sort(node+l,node+mid+1,[](const NODE& _x,const NODE &_y) {return _x.val < _y.val;});
std :: sort(node+mid+1,node+r+1,[](const NODE& _x,const NODE &_y) {return _x.val < _y.val;});
register int i, j;
for(i = mid+1, j = l-1;i <= r;++i) {
while(j < mid&&node[j+1].val < node[i].val) {
++j;
modify(node[j].time,1);
}
node[i].ans += query(node[i].time);
}
for(;j >= l;--j)
modify(node[j].time,-1);
for(i = mid, j = r;i >= l;--i) {
while(j > mid&&node[j].val > node[i].val) {
modify(node[j].time,1);
--j;
}
node[i].ans += query(node[i].time);
}
for(++j;j <= r;++j)
modify(node[j].time,-1);
}
int main() {
scanf("%d %d",&n,&m);
for(register int i = 1;i <= n;++i) {
scanf("%d",&node[i].val);
node[i].id = i;
pos[node[i].val] = i;
node[i].val = n-node[i].val+1;
}
for(register int i = 1, tmp;i <= m;++i) {
scanf("%d",&tmp);
node[pos[tmp]].time = m-i+1;
}
CDQ(1,n);
for(register int i = 1;i <= n;++i)
final_ans[node[i].time] += node[i].ans;
final_ans[1] >>= 1;
for(register int i = 1;i <= m;++i)
final_ans[i] += final_ans[i-1];
for(register int i = m;i >= 1;--i)
printf("%lld\n",final_ans[i]);
return 0;
}