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 + ;
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 (归并树)的更多相关文章
- HDU 5737 Differencia(归并树)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5737 [题目大意] 给出两个序列a和b,要求实现两个操作: 1. 将a序列的一个区间中的所有数改成 ...
- POJ2104 K-th Number(归并树)
平方分割一直TLE,最后用归并树处理过了,使用STL会比较慢. #include<cstdio> #include<iostream> #include<cstdlib& ...
- K-th Number 线段树(归并树)+二分查找
K-th Number 题意:给定一个包含n个不同数的数列a1, a2, ..., an 和m个三元组表示的查询.对于每个查询(i, j, k), 输出ai, ai+1, ... ,aj的升序排列中第 ...
- 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665
如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...
- POJ 2014.K-th Number 区间第k小 (归并树)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 57543 Accepted: 19893 Ca ...
- hdu 4417,poj 2104 划分树(模版)归并树(模版)
这次是彻底把划分树搞明确了,与此同一时候发现了模版的重要性.敲代码一个字符都不能错啊~~~ 划分树具体解释:点击打开链接 题意:求一组数列中随意区间不大于h的个数. 这个题的做法是用二分查询 求给定 ...
- 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 ...
- 静态区间第k大(归并树)
POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...
- POJ 2104 K-th Number(区间第k大数)(平方切割,归并树,划分树)
题目链接: http://poj.org/problem? id=2104 解题思路: 由于查询的个数m非常大.朴素的求法无法在规定时间内求解. 因此应该选用合理的方式维护数据来做到高效地查询. 假设 ...
随机推荐
- java System类的一些静态方法
package cn.sasa.demo2; public class SystemDemo { public static void main(String[] args) { func_array ...
- Python Mock的入门(转)
原文:https://segmentfault.com/a/1190000002965620 Mock是什么 Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西. ...
- (4.20)sql server中 len 与datalength 的区别
len是任意字符均为一个占位符字节.datalength是根据字符集不同判断占用,如一个中文占用2个字节.
- navicat如何导出mysql数据表结构
我们在创建数据库时会对字段进行设置,比如类型.长度等,如果字段多的话一个个设置非常麻烦,可以从其他地方已有的表导入数据表结构,怎么操作呢?我们拿navicat导出mysql数据表结构为例: 1.点击“ ...
- Centos7之Systemd风格
Unit(单元) /usr/lib/systemd/system 每个服务最主要的启动脚本设置,类似于之前的/etc/init.d目录 关键特性 1.基于socket的激活机制,socke ...
- WD 蓝盘、绿盘、黑盘、红盘的区别
绿盘,蓝盘.黑盘和红盘是西部数据根据旗下所产硬盘的特点所做的分类,通俗点讲:所谓的黑盘.蓝盘.绿盘.红盘就是指的西部数据硬盘上贴的那张纸,是黑色.蓝色.绿色.或红色. 黑盘:高性能,大缓存,速度快.代 ...
- iframe子父窗口相互操作方法或元素
一.jquery 父.子页面之间页面元素的获取,方法的调用: 1. 父页面获取子页面元素: 格式:$("#iframe的ID").contents().find("#if ...
- vue中indexDB的应用
// indexedDB.js,浏览器本地数据库操作 export default { // indexedDB兼容 indexedDB: window.indexedDB || window.web ...
- 自己实现strtok函数
思路:每次在原来字符串中查找分隔字符串,将分隔字符串中所有字符设为'\0',然后输出分隔串前的子串,同时更新原串的起始位置. PS:有不少博客作者自己实现的方法中往往只将分隔串当做一个字符,实际上可以 ...
- Python生态工具、文本处理和系统管理(虚拟)
一.Python生态工具 一.Python内置小工具 1.秒级启动一个下载服务器 Python 内置了一个下载服务器就能够显著提升效率了 . 例如, 你的同事要让你传的文件位于某一个目录下,那么,你可 ...