1. 程式人生 > 其它 >dls的資料結構-掃描線與權值線段樹

dls的資料結構-掃描線與權值線段樹

二維數點
1. 兩條限制,x1=<x<=x2, y1=<y<=y2, 我們可以將其轉化成單邊界的問題
2. 對於上面類似的問題都可以轉換成掃描線的形式,在該題中掃y,對x進行計數
3. 也有離線的思想
4. 事件的思想
5. vx離散化只需要離散點的x就行了,其他的不需要離散,其中lowber_bound + 1求第一個==的座標,upper_bound求最後一個<=他的座標
#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 3e5+10;
vector<array<int, 4>> events;
vector<int> vx;
int res[N];

LL tr[N];
int m;
int lowbit(int x){
    return x & (-x);
}

int modify(int x, LL v){
    for(int i = x; i <= m; i += lowbit(i)) tr[i] += v;
}

LL query(int x){
    LL sum = 0;
    for(int i = x; i; i -= lowbit(i)) sum += tr[i];
    return sum;
}

int main(){
    int n, q; scanf("%d %d", &n, &q);
    for(int i = 1; i <= n; i ++){
        int x, y; scanf("%d %d", &x, &y);
        events.push_back({y, 0, x});
        vx.push_back(x);
    }    
    for(int i = 1; i <= q; i ++){
        int x1, y1, x2, y2; scanf("%d %d %d %d", &x1, &x2, &y1, &y2);
        events.push_back({y2, 1, x2, i});
        events.push_back({y1 - 1, 1, x1 - 1, i});
        events.push_back({y1 - 1, 2, x2, i});
        events.push_back({y2, 2, x1 - 1, i});
    }
    sort(events.begin(), events.end());
    sort(vx.begin(), vx.end());
    vx.erase(unique(vx.begin(), vx.end()), vx.end());
    m = vx.size() ;
    for(auto evt : events){
        if(evt[1] == 0){
            int x = lower_bound(vx.begin(), vx.end(), evt[2] ) - vx.begin() + 1;
            modify(x, 1);
        }
        else{
            int x = upper_bound(vx.begin(), vx.end(), evt[2]) - vx.begin();
            res[evt[3]] += (evt[1] == 1) ? query(x) : -1 * query(x);
        }
    }
    for(int i = 1; i <= q; i ++){
        printf("%d\n", res[i]);
    }
    return 0;
}