• 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
  • 相关阅读:
    【CF 359B】Permutation
    如何更新 DevC++ 的编译器
    【LG 2801】教主的魔法
    矩阵浅谈
    NOI 系列赛常见技术问题整理
    Treap 浅谈
    DP 优化浅谈
    友链
    【CF 708C】Centroids
    我跳过的坑
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3110.html
Copyright © 2020-2023  润新知