归并树,与我们原学过的归并排序是一样的原理,但是在那个的基础上进行扩展应用。首先每个节点储存了它每个节点所代表的点的有序序列,还有就是每个点里面包含的所有的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. (转载)centos7启用端口

    转载:原文地址:https://www.cnblogs.com/moxiaoan/p/5683743.html   1.firewalld的基本使用 启动: systemctl start firew ...

  2. Shell基本介绍和使用

    Shell 教程 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个 ...

  3. 20165336 实验一 Java开发环境的熟悉

    20165336 实验一 Java开发环境的熟悉 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:康志强 学号:20165336 指导教师:娄嘉鹏 实验日期:2018年4月2日 实验 ...

  4. centos7.2 mysql5.5编译安装

    环境 centos7.2 源码包mysql5.5.38 mysql5.5开始,源码配置编译工具configure变成了cmake,所以先要去把cmake装上.并安装make,bison,cmake,g ...

  5. SSIS--(1)

    目标:两组数据比对,A 来源Excel ,B 来源 Sql server DB ,比对合并,取值放入目标 C 中 首先使用工具SSIS包 一,以数据源 A 为准核对B 中是否有A 的数据和计算等动作 ...

  6. 简明 ASP.NET Core 手册2018

    https://windsting.github.io/little-aspnetcore-book/book/ 中文版 https://nbarbettini.gitbooks.io/little- ...

  7. NYOJ 布线问题

    #include<iostream> #include<stdio.h> #include<queue> #include<algorithm> usi ...

  8. 解决npm ERR! Unexpected end of JSON input while parsing near的方法汇总

    参考链接:https://segmentfault.com/a/1190000015646531

  9. tomcat调试之固定步骤自动化

    前端开发,使用tomcat调试,大致需要进行如下几个步骤.其中,第一步,进入项目所在目录敲sbt命令来打包,第二步,拷贝lib文件夹,第四步重启tomcat,反反复复已经让我不胜其烦,那么做个简单的b ...

  10. Sublime Text 许可证

    ----- BEGIN LICENSE Alexander Single User License EA7E- 51F47F09 4EAB1285 7827EFF0 8B1207DC A76A6EA3 ...