1. 程式人生 > 其它 >HDU - 6534 Chika and Friendly Pairs(樹狀陣列+莫隊)

HDU - 6534 Chika and Friendly Pairs(樹狀陣列+莫隊)

題目連結

題目大意

  詢問區間[l,r]中滿足相鄰兩個樹大小不超過k的數對。

解題思路

  如果一個一個加入數字的話,設當前數字為i,那麼對答案的貢獻就是之前的數字之中\([a_i-k,a_i+k]\)範圍內的數字的數量,可以用莫隊來維護l,r,然後每次的修改和查詢操作用樹狀陣列來操作。

程式碼

const int maxn = 1e5+10;
const int maxm = 1e6+10;
int n, nn, m, k;
int a[maxn], b[maxn], p[maxn];
int find(int x) {
    return lower_bound(b+1, b+nn+1, x)-b;
}
int find2(int x) {
    return upper_bound(b+1, b+nn+1, x)-b;
}
int c[maxn];
void insert(int x, int y) {
    while(x<=n) {
        c[x] += y;
        x += x&-x;
    }
}
int ask(int x) {
    int sum = 0;
    while(x) {
        sum += c[x];
        x -= x&-x;
    }
    return sum;
}
struct Q {
    int l, r, i;
} q[maxn];
    int l = 1, r = 0;
int ans[maxn], res, up[maxn], low[maxn];
void add(int x) {
    res += ask(up[x])-ask(low[x]-1);
    insert(a[x], 1);
}
void sub(int x) {
    insert(a[x], -1);
    res -= ask(up[x])-ask(low[x]-1);
    //cout << a[x] << ' ' << l << ' ' << r << ' ' << res << endl;
}
int main() {
    IOS;    
    cin >> n >> m >> k;
    for (int i = 1; i<=n; ++i) cin >> a[i], b[i] = a[i];
    sort(b+1, b+n+1);
    nn = unique(b+1, b+n+1)-b-1;
    for (int i = 1; i<=n; ++i) {
        low[i] = find(a[i]-k);
        up[i] = find2(a[i]+k)-1;
        a[i] = find(a[i]);
        //cout << low[i] << ' ' << a[i] << ' ' << up[i] << endl;
    }
    for (int i = 1; i<=m; ++i) {
        cin >> q[i].l >> q[i].r;
        q[i].i = i;
    }
    int sz = sqrt(m)+1;
    sort(q+1, q+m+1, [=](Q x, Q y) {return (x.l/sz^y.l/sz) ? x.l/sz<y.l/sz : ((x.l/sz)%2 ? x.r<y.r:x.r>y.r);});
    for (int i = 1; i<=m; ++i) {
        //cout << q[i].l << ' ' << q[i].r << endl;
        while(q[i].r > r) add(++r);
        //cout << res << endl;
        while(q[i].l > l) sub(l++);
        //cout << res << endl;
        while(q[i].r < r) sub(r--);
        //cout << res << endl;
        while(q[i].l < l) add(--l);
        //cout << res << endl;
        ans[q[i].i] = res;
    }
    for (int i = 1; i<=m; ++i) cout << ans[i] << endl;
    return 0;
}