归并树,与我们原学过的归并排序是一样的原理,但是在那个的基础上进行扩展应用。首先每个节点储存了它每个节点所代表的点的有序序列,还有就是每个点里面包含的所有的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 + ;
const int maxn = ; int T, n, m, ans, last, cnt, L, R, X;
int a[maxn], b[maxn], st[maxn * ], en[maxn * ], lazy[maxn * ], num[maxn * ];
int pl[maxn * ], pr[maxn * ], pool[maxn * ]; void Build(int l, int r, int rt){
lazy[rt] = -;
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 + , 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 + ;
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 - ; pr[i] = rightL - ;
if(pl[i] < st[Lson]) pl[i] = ;
if(pr[i] < st[Rson]) pr[i] = ;
}
} void Lazy(int rt, int pos){
num[rt] = pos ? pos - st[rt] + : ;
lazy[rt] = pos;
} void Pushdown(int rt){
if(lazy[rt] == -) return ;
int pos = lazy[rt];
Lazy(Lson, pl[pos]);
Lazy(Rson, pr[pos]);
lazy[rt] = -;
} int erfen(int x){
int l = st[], r = en[], ans = ;
while(l <= r){
if(pool[M] <= x){ ans = M; l = M + ;}
else r = M - ;
}
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 + , 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 = ~(<<),MM = (<<) - ;
int rnd(){
AA = ( + (last >> )) * (AA&MM) + (AA >> );
BB = ( + (last >> )) * (BB&MM) + (BB >> );
return (CC & ((AA << ) + BB)) % ;
} int main(){
int n,m;
scanf("%d", &T);while(T --){
ans = last = cnt = ;
scanf("%d%d%d%d", &n, &m, &AA, &BB);
for(int i = ; i <= n; i ++) scanf("%d",&a[i]);
for(int i = ; i <= n; i ++) scanf("%d",&b[i]);
Build(, n, ); for(int i = ; i <= m; i ++){
L = rnd()%n + ; R = rnd()%n + ; X = rnd() + ;
if(L > R)swap(L, R);
if((L + R + X) & )
Update(, n, erfen(X), );
else{
last = ;
query(, n, );
ans = (1LL * i * last % mod + ans) % mod;
}
}
printf("%d\n",ans);
}
return ;
}

Differencia (归并树)的更多相关文章

  1. HDU 5737 Differencia(归并树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5737 [题目大意] 给出两个序列a和b,要求实现两个操作: 1. 将a序列的一个区间中的所有数改成 ...

  2. POJ2104 K-th Number(归并树)

    平方分割一直TLE,最后用归并树处理过了,使用STL会比较慢. #include<cstdio> #include<iostream> #include<cstdlib& ...

  3. K-th Number 线段树(归并树)+二分查找

    K-th Number 题意:给定一个包含n个不同数的数列a1, a2, ..., an 和m个三元组表示的查询.对于每个查询(i, j, k), 输出ai, ai+1, ... ,aj的升序排列中第 ...

  4. 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

    如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...

  5. POJ 2014.K-th Number 区间第k小 (归并树)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 57543   Accepted: 19893 Ca ...

  6. hdu 4417,poj 2104 划分树(模版)归并树(模版)

    这次是彻底把划分树搞明确了,与此同一时候发现了模版的重要性.敲代码一个字符都不能错啊~~~ 划分树具体解释:点击打开链接 题意:求一组数列中随意区间不大于h的个数. 这个题的做法是用二分查询  求给定 ...

  7. SPOJ:K-Query Online(归并树)

    Given a sequence of n numbers a1, a2, ..., an and a number of k-queries. A k-query is a triple (i, j ...

  8. 静态区间第k大(归并树)

    POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...

  9. POJ 2104 K-th Number(区间第k大数)(平方切割,归并树,划分树)

    题目链接: http://poj.org/problem? id=2104 解题思路: 由于查询的个数m非常大.朴素的求法无法在规定时间内求解. 因此应该选用合理的方式维护数据来做到高效地查询. 假设 ...

随机推荐

  1. 为QtCreator项目模板添加自动中文支持

    每用QtCreator创建一个Qt项目时都要为它添加中文支持,比如qt4: 就要在main.cpp里添加 QTextCodec* codec = QTextCodec::codecForName(&q ...

  2. Matlab 快捷键 命令

    1. 在命令窗口(Command Window)中: 1) [上.下键]――切换到之前.之后的命令,可以重复按多次来达到你想要的命令 2) clc――清除命令窗口显示的语句,此命令并不清空当前工作区的 ...

  3. 第四章:初识CSS3

    1.CSS规则由两部分构成,即选择器和声明器 声明必须放在{}中并且声明可以是一条或者多条 每条声明由一个属性和值构成,属性和值用冒号分开,每条语句用英文冒号分开 注意: css的最后一条声明,用以结 ...

  4. 1-4-bootloader架构学习

    1-4-bootloader架构学习 1.一般情况下嵌入式 Linux 系统中的软件主要分为以下几部分: 1) 引导加载程序:其中包括内部 ROM 中的固化启动代码和 BootLoader 两部分. ...

  5. JavaScript学习(八)

  6. JSON.parseObject 和 JSON.toJSONString

    JSON.parseObject,是将Json字符串转化为相应的对象:JSON.toJSONString则是将对象转化为Json字符串.在前后台的传输过程中,Json字符串是相当常用的,这里就不多介绍 ...

  7. 【托业】【新托业TOEIC新题型真题】学习笔记8-题库五->P7

    ———————————————————单词———————————————————— minister 部长 construction contractor 施工方 commence 开始:着手 bac ...

  8. echart 设计宽度为百分比时,div撑不开

    解决思路:将百分比换算成px 一句话搞定 ("#chart").css( 'width', $("#chart").width() );$("#cha ...

  9. android常用函数

    package com.cqytjr.util; import java.io.File; import java.net.InetAddress; import java.net.NetworkIn ...

  10. jenkins的pipeline的使用

    1.安装Pipeline Maven Integration Plugin 2.新建任务 3.编写pipeline代码 node { stage('get clone') { checkout([$c ...