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非常大.朴素的求法无法在规定时间内求解. 因此应该选用合理的方式维护数据来做到高效地查询. 假设 ...
随机推荐
- adb devices offline的解决办法
手机通过USB线连接电脑后,输入adb devices 识别为 offline,如图: 解决办法如下: (0) 换数据线.换主机后面的USB口先试一下 (1) 重启adb服务 adb kill-ser ...
- python编码类型互转总结
1.只有在unicode下才能将utf-8与gbk互转2.unicode是在内存中使用,bytes是文件存储和网络传输时使用-------------------------------------- ...
- java 线程(六)死锁
package cn.sasa.demo4; public class ThreadDemo { public static void main(String[] args){ DeadLockRun ...
- sql-server数据库常用语句
查看所有数据库名 select name from master..Sysdatabases order by name; 查看当前数据所有表 select name from sysobjects ...
- Apache Spark支持三种分布式部署方式 standalone、spark on mesos和 spark on YARN区别
链接地址: http://dongxicheng.org/framework-on-yarn/apache-spark-comparing-three-deploying-ways/ Spark On ...
- Matlab中导入文本文件中的数据 矩阵合并 以及C++中删除文件操作
今天用到了Matlab读取文本文件中按照一定格式存储好的数据,然后进行后续的分析计算等,因此涉及到Matlab的文件读取,记录在这里,供以后查阅: fid = fopen('train.set', ' ...
- discuz论坛 模板修改
门户首页 template/rtj1009_007/portal/index.php 头部二级导航 template/rtj1009_007/common/toubu.php 底部内容文件 templ ...
- 微信小程序使用阿里图标-iconfont
步骤一:下载项目图标 步骤二:解压文件,重命名 iconfont.css为 iconfont.wxss ,并复制 到项目 static文件夹 icon文件夹下 ...
- 基于nodejs的 本地文件夹http服务器:http-server
请记住,是文件夹服务器 $ npm install http-server -g $ cd /tmp && http-server 或: $ http-server /tmp
- Jquery书写AJAX动态向页面form传数据,清空之前的数据
三种方式: 直接代码: 1.$("#mytable tr:gt(0)").remove(); 2.$("#mytable tr:not(:first)").em ...