• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
镂空的行尸
   首页       联系   管理    订阅  订阅

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\n",ans);
    }
    return 0;
}

 

more crazy more get!
posted @ 2018-10-08 01:28  镂空的行尸  阅读(211)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3