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+y看作z,(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、会出现相等的值