【洛谷P3810】 【模板】三維偏序(陌上花開)

CDQ是一中思想,用來求點對數列。
定義\(solve(l,r)\)用來求\([l,r]\)區間的數對,
那麼先遞歸處理\(solve(l,mid)\)
然後考慮前半段對後半段的影響,
然後再遞歸處理後半段\(solve(mid+1,r)\)

對於這道題,具體就是,先按\(a\)排序,然後\(solve(l,r)\)先遞歸處理兩邊,然後考慮怎麼統計\(i\)在前半段,\(j\)在後半段的滿足\(b_i\leq b_j\)\(c_i\leq c_j\)的個數。
可以先對這兩端按\(b\)排序,然後雙指針一個個把左邊的\(c\)插到樹狀數組裏,枚舉右邊的直接統計。

#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define pb push_back
#define rep(i, m, n) for(int i = (m); i <= (n); ++i)
#define dop(i, m, n) for(int i = (m); i >= (n); --i)
#define all(x) x.begin(), x.end()
#define Open(s) freopen(s,"r",stdin);
#define Write(s) freopen(s,"w",stdout);
using namespace std;
typedef long long ll;
template <class T> void chkmin(T &a, T b){ if(a > b) a = b; }
template <class T> void chkmax(T &a, T b){ if(a < b) a = b; }
template <class T> T aabs(T a){ return a > 0 ? a : -a; }
const int N = 200010;
struct node{
	int num, a, b, c, ans;
	void input(){
		scanf("%d%d%d", &a, &b, &c);
	}
}q[N], p[N];
int n, k;
int cmp(const node& a, const node& b){
	return a.b != b.b ? a.b < b.b : a.c < b.c;
};
int s[N], cnt[N];
void add(int x, int y){
	while(x <= k){
		s[x] += y;
		x += lowbit(x);
	}
}
int ask(int x){
	int ans = 0;
	while(x){
		ans += s[x];
		x -= lowbit(x);
	}
	return ans;
}
void solve(int l, int r){
	if(l == r) return;
	int mid = l + r >> 1;
	solve(l, mid); solve(mid + 1, r);
	sort(p+l, p+mid+1, cmp);
	sort(p+mid+1, p+r+1, cmp);
	int cur = l - 1;
	rep(i, mid+1, r){
		while(cur < mid && p[cur+1].b <= p[i].b){
			++cur; add(p[cur].c, p[cur].num);
		}
		p[i].ans += ask(p[i].c);
	}
	rep(i, l, cur) add(p[i].c, -p[i].num);
}
int main(){
	scanf("%d%d", &n, &k); int m = n;
	rep(i, 1, n) q[i].input();
	sort(q+1, q+n+1, [](node& a, node& b){
		return a.a != b.a ? a.a < b.a : (a.b != b.b ? a.b < b.b : a.c < b.c);
	});
	n = 0;
	rep(i, 1, m){
		if(q[i].a != q[i-1].a || q[i].b != q[i-1].b || q[i].c != q[i-1].c){
			p[++n] = q[i]; p[n].num = 1;
		}
		else p[n].num++;
	}
	solve(1, n);
	rep(i, 1, n) cnt[p[i].ans + p[i].num - 1] += p[i].num;
	rep(i, 0, m-1) printf("%d\n", cnt[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章