二维偏序

二维偏序

二维偏序一般指这样一种问题:

比如:

​ 有\(n\) 个点(或别的),都有两个属性,\(\{(a_1,b_1),(a_2,b_2)...\}\)并且对于其中两个点\(i 和 j\) 满足

\[\begin{cases} i \leq j \leq n \\ a_i \leq a_j \\ b_i \leq b_j \end{cases} \]

一般解法是 排序一维 后 使用树状数组存储下一维的信息 ,有时候需要离散化

一些例题+code

逆序对模板题

const int maxn = 5e5 + 10;

int n,m;
int a[maxn],b[maxn],c[maxn];
int lowbit(int x) { return  (x & (-x)); }
void add(int x) {
	for(int i = x; i <= n; i += lowbit(i)) {
		c[i]++;
	}
}
int query(int x) {
	int sum = 0;
	for(int i = x ; i ; i -= lowbit(i)) {
		sum += c[i];
	}
	return sum;
}
int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> b[i];
		a[i] = b[i];
	}
	sort(a+1,a+1+n );
	int m = unique(a+1,a+1+n) - a - 1;
	for(int i = 1; i <= n; i++) {
		b[i] = lower_bound(a+1,a+m+1,b[i] ) - a;
	}
	ll ans = 0;
	for(int i = 1; i <= n; i++) {
		add(b[i]);
		ans += (i - query(b[i]));
	}
	cout << ans << "\n";
	return 0;
}

CF1311F Moving Points

int n,m;
int b[maxn],p[maxn];
int c1[maxn],c2[maxn];
struct node{
	int x,v;
}a[maxn];
int lowbit(int x) { return x & -x; }
void add1(int x,int k) {
	for(int i = x; i <= n; i += lowbit(i)) {
		c1[i]++;
	}
}
int que1(int x) {
	int ans = 0 ;
	for(int i = x; i; i -= lowbit(i)) {
		ans += c1[i];
	}
	return ans;
}
void add2(int x,int k) {
	for(int i = x; i <= n; i += lowbit(i)) {
		c2[i] += k;
	}
}
int que2(int x) {
	int ans = 0 ;
	for(int i = x; i; i -= lowbit(i)) {
		ans += c2[i];
	}
	return ans;
}
pii v[maxn];
signed main() {
	cin >> n;
	for(int i = 1; i <= n; i++)	{
		cin >> a[i].x;
	}
	for(int i = 1; i <= n; i++) {
		cin >> a[i].v;
		b[i] = a[i].v;
	}
	sort(b+1,b+1+n);
	m = unique(b+1,b+1+n) - b - 1;
	for(int i = 1; i <= n; i++) {
		a[i].v = lower_bound(b+1,b+1+n,a[i].v) - b;
	}
	sort(a+1,a+1+n,[](node x,node y){
		return x.x < y.x;
	});
	ll ans = 0;
	for(int i = 1; i <= n; i++) {
		int cnt = que1(a[i].v);
		int sum = que2(a[i].v);
		ans += (cnt * a[i].x - sum);
		add1(a[i].v,1);
		add2(a[i].v,a[i].x);
	}
	cout << ans << "\n";
 
	return 0;
}

P5094 [USACO04OPEN]MooFest

这一题和上面哪一题非常像

int n,m;
int c1[maxn],c2[maxn];
int lowbit(int x) { return (x  & -x); }
void add1(int x,int k) {
	for(int i = x; i <= m; i += lowbit(i)) {
		c1[i]++;
	}
}
int que1(int x) {
	int ans = 0;
	for(int i = x; i; i -= lowbit(i)) {
		ans += c1[i];
	}
	return ans;
}
void add2(int x,int k) {
	for(int i = x; i <= m; i+= lowbit(i)) {
		c2[i] += k;
	}
}
int que2(int x) {
	int ans = 0;
	for(int i = x; i; i -= lowbit(i)) {
		ans += c2[i];
	}
	return ans;
}
struct node{
	int v,x;
}a[maxn];
signed main() {
	cin >> n;	
	for(int i = 1; i <= n; i++) {
		cin >> a[i].v >> a[i].x;
		m = max(a[i].x,m);
	}
	sort(a+1,a+1+n,[](node a,node b){
		return a.v < b.v;
	});
	ll ans = 0;
	int p = 0;
	for(int i = 1; i <= n; i++) {
		int cnt = que1(a[i].x);
		int sum = que2(a[i].x);
		ans += (cnt * a[i].x - sum) * a[i].v;
		ans += (p - sum - (i - cnt - 1)*a[i].x) * a[i].v;
		add1(a[i].x, 1);
		add2(a[i].x,a[i].x);
		p += a[i].x;
	}
	cout << ans << "\n";
	return 0;
}
posted @ 2021-03-31 23:46  EnthalpyDecreaser  阅读(294)  评论(0编辑  收藏  举报