zoukankan      html  css  js  c++  java
  • Differencia (归并树)

    归并树,与我们原学过的归并排序是一样的原理,但是在那个的基础上进行扩展应用。首先每个节点储存了它每个节点所代表的点的有序序列,还有就是每个点里面包含的所有的b[i]在左右子树的排名辅助更新数据,还有一个用来记录当前节点a[] >b[] 的数量的num。这时候查询的话就是线段树查询了,然后更新,首先求出要更新进去的点在原本数组的排名,然后就可以将该数据更新进去范围里面的lazy数组了,那么这时候lazy数组怎么使用?其实你这个lazy数组就是你更新进来的数据在确定范围内的一个排名,那么你这个排名就是a[] > b[] 的数量了。当然不可能更新所有的节点,所以需要使用lazydown的方法优化时间。

    #include<bits/stdc++.h>
    #define debug 0
    #define Lson (rt << 1)
    #define Rson ((rt << 1) | 1)
    #define M ((l + r) / 2)
    
    using namespace std;
    
    const long long mod  = 1e9 + 7;
    const int maxn = 111111;
    
    int T, n, m, ans, last, cnt, L, R, X;
    int a[maxn], b[maxn], st[maxn * 4], en[maxn * 4], lazy[maxn * 4], num[maxn * 4];
    int pl[maxn * 17], pr[maxn * 17], pool[maxn * 17];
    
    void Build(int l, int r, int rt){
        lazy[rt] = -1;
        if(l == r){
            st[rt] = ++cnt;en[rt] = cnt;
            pool[cnt] = b[l];
            num[rt] = (a[l] >= b[l]);
            return ;
        }
        Build(l, M, Lson);Build(M + 1, r, Rson);
        num[rt] = num[Lson] + num[Rson];
        int leftL = st[Lson], leftR = en[Lson];
        int rightL = st[Rson], rightR = en[Rson];
    
        st[rt] = cnt + 1;
        while(leftL <= leftR && rightL <= rightR)pool[++cnt] = ((pool[leftL] <= pool[rightL]) ? pool[leftL ++] : pool[rightL ++]);
        while(leftL <= leftR)pool[++cnt] = pool[leftL ++];
        while(rightL <= rightR)pool[++cnt] = pool[rightL ++];
        en[rt] = cnt;
    
        leftL = st[Lson], rightL = st[Rson];
        for(int i = st[rt]; i <= en[rt]; i ++){
            while(leftL <= leftR && pool[leftL] <= pool[i]) leftL ++;
            while(rightL <= rightR && pool[rightL] <= pool[i]) rightL ++;
            pl[i] = leftL - 1; pr[i] = rightL - 1;
            if(pl[i] < st[Lson]) pl[i] = 0;
            if(pr[i] < st[Rson]) pr[i] = 0;
        }
    }
    
    void Lazy(int rt, int pos){
        num[rt] = pos ? pos - st[rt] + 1 : 0;
        lazy[rt] = pos;
    }
    
    void Pushdown(int rt){
        if(lazy[rt] == -1) return ;
        int pos = lazy[rt];
        Lazy(Lson, pl[pos]);
        Lazy(Rson, pr[pos]);
        lazy[rt] = -1;
    }
    
    int erfen(int x){
        int l = st[1], r = en[1], ans = 0;
        while(l <= r){
            if(pool[M] <= x){ ans = M; l = M + 1;}
            else r = M - 1;
        }
        return ans;
    }
    
    void query(int l, int r, int rt){
        if(L <= l && r <= R){
            last += num[rt];
            return ;
        }
        Pushdown(rt);
        if(L <= M) query(l, M, Lson);
        if(R > M) query(M + 1, r, Rson);
        num[rt] = num[Lson] + num[Rson];
    }
    
    void Update(int l, int r, int pos, int rt){
        if(L <= l && r <= R){
            Lazy(rt, pos);return ;
        }
        Pushdown(rt);
        if(L <= M) Update(l, M, pl[pos], Lson);
        if(R >  M) Update(M + z1, r, pr[pos], Rson);
        num[rt] = num[Lson] + num[Rson];
    }
    
    int AA,BB,CC = ~(1<<31),MM = (1<<16) - 1;
    int rnd(){
        AA = (36969 + (last >> 3)) * (AA&MM) + (AA >> 16);
        BB = (18000 + (last >> 3)) * (BB&MM) + (BB >> 16);
        return (CC & ((AA << 16) + BB)) % 1000000000;
    }
    
    int main(){
        int n,m;
        scanf("%d", &T);while(T --){
            ans = last = cnt = 0;
            scanf("%d%d%d%d", &n, &m, &AA, &BB);
            for(int i = 1; i <= n; i ++) scanf("%d",&a[i]);
            for(int i = 1; i <= n; i ++) scanf("%d",&b[i]);
            Build(1, n, 1);
    
            for(int i = 1; i <= m; i ++){
                L = rnd()%n + 1; R = rnd()%n + 1; X = rnd() + 1;
                if(L > R)swap(L, R);
                if((L + R + X) & 1)
                    Update(1, n, erfen(X), 1);
                else{
                    last = 0;
                    query(1, n, 1);
                    ans = (1LL * i * last % mod + ans) % mod;
                }
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    more crazy more get!
  • 相关阅读:
    SpringBoot第五篇:整合Mybatis
    SpringBoot第四篇:整合JDBCTemplate
    SpringBoot第三篇:配置文件详解二
    分享一篇去年的项目总结
    Oracle生成多表触发器sql
    Oracle 设置用户密码永不过期
    Oracle建表提示SQL 错误: ORA-00904: : 标识符无效
    MySql数据备份
    ETL全量多表同步简述
    ETL全量单表同步简述
  • 原文地址:https://www.cnblogs.com/wethura/p/9752269.html
Copyright © 2011-2022 走看看