loj #3030. 「JOISC 2019 Day1」考试

loj #3030. 「JOISC 2019 Day1」考试

大意

很清楚啊

题解

把 x + y 看 作 z , ( x , y , x + y ) − − − > ( x , y , z ) 就 是 一 个 很 裸 的 三 维 偏 序 问 题 把x+y看作z,(x, y, x+y) ---> (x,y,z) 就是一个很裸的三维偏序问题 x+yz(x,y,x+y)>(x,y,z)


#include<bits/stdc++.h>
#define lowbit(x) (x & -x)
#define N 5000005
using namespace std;
struct Q{
	int x, y, z, id;
}q[N], b[N];
int operator < (Q x, Q y){//注意从大到小
	return x.x > y.x;
}
int cmp(Q x, Q y){//因为可能会出现相等的,所以要特判
	if(x.z != y.z) return x.z > y.z;
	if(x.y != y.y) return x.y > y.y;
	if(x.x != y.x) return x.x > y.x;
	return x.id < y.id;
}
int tree[N], tot, aa[N];
void update(int x, int y){
	for(; x < N; x += lowbit(x)) tree[x] += y;
}
int query(int x){
	int ret = 0;
	for(; x; x -= lowbit(x)) ret += tree[x];
	return ret;
}
int ANS[N], del[N], n, m;
void cdq(int l, int r){//三维偏序板子,不过注意这里是从大到小
	if(l == r) return;
	int mid = (l + r) >> 1;
	cdq(l, mid), cdq(mid + 1, r);
	int sz = 0, pos = l - 1;
	for(int i =  mid + 1; i <= r; i ++){
		while(q[pos + 1].x >= q[i].x && pos < mid){
			pos ++;
			if(q[pos].id == 0) update(q[pos].y, 1), del[++ sz] = pos;
		}
		if(q[i].id) ANS[q[i].id] += query(N - 1) - query(q[i].y - 1);
	}
	for(int i = 1; i <= sz; i ++) update(q[del[i]].y, -1);
	merge(q + l, q + mid + 1, q + mid + 1, q + r + 1, b + l);
	for(int i = l; i <= r; i ++) q[i] = b[i];
}
int main(){
	scanf("%d%d", &n, &m);
	int s = 0;
	for(int i = 1; i <= n; i ++){
		tot ++;
		scanf("%d%d", &q[tot].x, &q[tot].y);
		q[tot].z = q[tot].x + q[tot].y;
		aa[++ s] = q[tot].x, aa[++ s] = q[tot].y, aa[++ s] = q[tot].z;
	}
	
	for(int i = 1; i <= m; i ++){
		tot ++;
		scanf("%d%d%d", &q[tot].x, &q[tot].y, &q[tot].z);
		aa[++ s] = q[tot].x, aa[++ s] = q[tot].y, aa[++ s] = q[tot].z;
		q[tot].id = i;
	}
	sort(aa + 1, aa + s + 1);
	
	for(int i = 1; i <= tot; i ++){//记得离散化
		q[i].x = lower_bound(aa + 1, aa + s + 1, q[i].x) - aa;
		q[i].y = lower_bound(aa + 1, aa + s + 1, q[i].y) - aa;
		q[i].z = lower_bound(aa + 1, aa + s + 1, q[i].z) - aa;
	}
	sort(q + 1, q + 1 + tot, cmp);
	
//	for(int i = 1; i <= tot; i ++) printf("%d %d %d   %d\n", q[i].x, q[i].y, q[i].z, q[i].id);
	cdq(1, tot);
	for(int i = 1; i <= m; i ++) printf("%d\n", ANS[i]);
	return 0;
}

坑点

1、离散化
2、会出现相等的值

posted @ 2019-08-16 11:55  lahlah  阅读(37)  评论(0编辑  收藏  举报