zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第七场)- Find the median

    线段树

    显然的方法是把区间离散化以后,维护每个区间内出现的数的个数。

    查询的时候直接用左端点的值加上查询的数的排名/区间插入的次数就行了。

    处理这类问题一般是让每个端点的右区间+1,然后用叶子节点来保存一段区间的信息。

    当我们的线段树递归到叶子结点的时候,l = r, 我们如果让线段树维护当前区间每个数出现的次数,叶子节点显然不好处理,因为l = r。

    所以我们可以让每个区间维护的信息往后扩展一点。

    假设当前区间为[l...r], 这里l和r均为离散化以后的值。此时可以让线段树维护[l..r+1)区间内每个数出现的次数,这样到了叶子节点实际上是[l, l+1)区间内每个数出现的次数,(此时l=r)。

    这样问题就简化完成了。

    在修改的时候也要让右端点-1,这样才符合我们对维护的信息的定义.

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    #define __fastIn ios::sync_with_stdio(false), cin.tie(0)
    #define range(x) (x).begin(), (x).end()
    #define pb push_back
    using namespace std;
    typedef long long LL;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int ret = 0, w = 0; char ch = 0;
        while(!isdigit(ch)){
            w |= ch == '-', ch = getchar();
        }
        while(isdigit(ch)){
            ret = (ret << 3) + (ret << 1) + (ch ^ 48);
            ch = getchar();
        }
        return w ? -ret : ret;
    }
    template <typename A>
    inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }
    template <typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 400005;
    int n, x[N], y[N], L[N], R[N], a1, b1, c1, a2, b2, c2, m1, m2, b[N<<1], tot;
    int lazy[N<<3];
    LL freq[N<<3];
     
    void add(int rt, int l, int r, int val){
        lazy[rt] += val;
        freq[rt] += 1LL * (b[r + 1] - b[l]) * val;
    }
     
    void push_down(int rt, int l, int r, int val){
        int mid = (l + r) >> 1;
        add(rt << 1, l, mid, val);
        add(rt << 1 | 1, mid + 1, r, val);
        lazy[rt] = 0;
    }
     
    void push_up(int rt){
        freq[rt] = freq[rt << 1] + freq[rt << 1 | 1];
    }
     
    void buildTree(int rt, int l, int r){
        if(l == r){
            freq[rt] = lazy[rt] = 0;
            return;
        }
        int mid = (l + r) >> 1;
        buildTree(rt << 1, l, mid);
        buildTree(rt << 1 | 1, mid + 1, r);
        push_up(rt);
    }
     
    void insert(int rt, int l, int r, int il, int ir){
        if(l == il && r == ir){
            add(rt, l, r, 1);
            return;
        }
        push_down(rt, l, r, lazy[rt]);
        int mid = (l + r) >> 1;
        if(ir <= mid) insert(rt << 1, l, mid, il, ir);
        else if(il > mid) insert(rt << 1 | 1, mid + 1, r, il, ir);
        else insert(rt << 1, l, mid, il, mid), insert(rt << 1 | 1, mid + 1, r, mid + 1, ir);
        push_up(rt);
    }
     
    int query(int rt, int l, int r, LL k){
        if(l > r) return 0;
        if(l == r){
            return b[l] + (k - 1) / lazy[rt];
        }
        push_down(rt, l, r, lazy[rt]);
        int mid = (l + r) >> 1;
        if(freq[rt << 1] >= k) return query(rt << 1, l, mid, k);
        return query(rt << 1 | 1, mid + 1, r, k - freq[rt << 1]);
    }
     
    int main(){
     
        scanf("%d", &n);
        scanf("%d%d%d%d%d%d", &x[1], &x[2], &a1, &b1, &c1, &m1);
        scanf("%d%d%d%d%d%d", &y[1], &y[2], &a2, &b2, &c2, &m2);
        for(int i = 3; i <= n; i ++){
            x[i] = (1LL * a1 * x[i - 1] + 1LL * b1 * x[i - 2] + c1) % m1;
            y[i] = (1LL * a2 * y[i - 1] + 1LL * b2 * y[i - 2] + c2) % m2;
        }
        for(int i = 1; i <= n; i ++){
            L[i] = min(x[i], y[i]) + 1;
            R[i] = max(x[i], y[i]) + 1;
            R[i] ++, b[++tot] = L[i], b[++tot] = R[i];
        }
        sort(b + 1, b + tot + 1);
        tot = (int)(unique(b + 1, b + tot + 1) - b - 1);
    //    b[tot + 1] = b[tot] + 1;
    //    tot ++;
        LL sum = 0;
        buildTree(1, 1, tot);
        for(int i = 1; i <= n; i ++){
            sum += R[i] - L[i];
            L[i] = (int)(lower_bound(b + 1, b + tot + 1, L[i]) - b);
            R[i] = (int)(lower_bound(b + 1, b + tot + 1, R[i]) - b);
            insert(1, 1, tot, L[i], R[i] - 1);
            printf("%d
    ", query(1, 1, tot, (sum + 1) / 2));
        }
        return 0;
    }
    
  • 相关阅读:
    php命令注入
    mysql事物
    安装php环境
    移除服务器缓存实例
    show user profile synchronization tools
    manual start user profile import
    JSON is undefined. Infopath Form People Picker in SharePoint 2013
    asp.net web 应用站点支持域账户登录
    Load sharepoint envirement by powershell
    sharepoint 2016 download
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/11328190.html
Copyright © 2011-2022 走看看