📚【模板】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;
}
posted @ 2022-07-20 21:45  bikuhiku  阅读(24)  评论(0编辑  收藏  举报