bzoj3110 [Zjoi2013]K大数查询

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3110

【题解】

整体二分,把op=1的c变成n-c+1这样值域就是[1,2n+1],然后就是第k小了这样好做,最后输出记得变回来。

我们定义过程solve(l,r,al,ar)表示答案在[l,r],待操作[al,ar]

那么我们把c<=mid的操作全部做上去,然后对询问和操作分类,撤回操作即可。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n, Q;
struct quest {
    int op, a, b, c;
    quest() {}
    quest(int op, int a, int b, int c) : op(op), a(a), b(b), c(c) {}
}a[M];

struct BIT {
    int n;
    ll c[M];
    # define lb(x) (x&(-x))
    inline void set(int _n) {
        n = _n;
        memset(c, 0, sizeof c);
    }
    inline void edt(int x, int d) {
        for (; x<=n; x+=lb(x)) c[x] += d;
    }
    inline ll sum(int x) {
        ll ret = 0;
        for (; x; x-=lb(x)) ret += c[x];
        return ret;
    }
};

struct BIT2 {
    int n;
    BIT a, b;
    inline void set(int _n) {
        n = _n;
        a.set(n), b.set(n);
    }
    inline void edt(int x, int y, int d) {
        a.edt(x, d); a.edt(y+1, -d);
        b.edt(x, (ll)d*x); b.edt(y+1, -(ll)d*(y+1));
    }
    inline ll sum(int x) {
        return a.sum(x) * (x+1) - b.sum(x);
    }
    inline ll sum(int x, int y) {
        return sum(y) - sum(x-1);
    }
}T;
        
ll cur[M];
int ans[M], id[M], t1[M], t2[M];
inline void solve(int l, int r, int al, int ar) {
    if(al > ar) return ;
//    printf("%d %d %d %d
", l, r, al, ar);
    if(l == r) {
        for (int i=al; i<=ar; ++i) 
            if(a[id[i]].op == 2) ans[id[i]] = l;
        return;
    }
//    for (int i=al; i<=ar; ++i) 
//        cout << id[i] << ",";
//    cout << endl << endl;
    ll tem;
    int mid = l+r>>1, t1n, t2n; t1n = t2n = 0;
    for (int i=al; i<=ar; ++i) {
        int x = id[i];
        if(a[x].op == 1) {
            if(a[x].c <= mid) {
                t1[++t1n] = x;
                T.edt(a[x].a, a[x].b, 1);
            } else t2[++t2n] = x;
        } else {
            if((tem = cur[x] + T.sum(a[x].a, a[x].b)) >= a[x].c) t1[++t1n] = x;
            else t2[++t2n] = x, cur[x] = tem;
        }
    }
    for (int i=al; i<=ar; ++i) {
        int x = id[i];
        if(a[x].op == 1) {
            if(a[x].c <= mid) T.edt(a[x].a, a[x].b, -1);
        }
    }
    int tn = al-1;
    for (int i=1; i<=t1n; ++i) id[++tn] = t1[i];
    t1n = tn;
    for (int i=1; i<=t2n; ++i) id[++tn] = t2[i];
    solve(l, mid, al, t1n);
    solve(mid+1, r, t1n+1, ar);    
}

int main() {
    cin >> n >> Q;
    for (int i=1; i<=Q; ++i) {
        scanf("%d%d%d%d", &a[i].op, &a[i].a, &a[i].b, &a[i].c);
        if(a[i].op == 1) a[i].c = n - a[i].c + 1;    
        id[i] = i;
    }
//    for (int i=1; i<=Q; ++i) printf("%d %d %d %d
", a[i].op, a[i].a, a[i].b, a[i].c);
    
    T.set(n);
    solve(1, n+n+1, 1, Q); 
    for (int i=1; i<=Q; ++i)
        if(a[i].op == 2) printf("%d
", n - ans[i] + 1);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/galaxies/p/bzoj3110.html