Hdu5737-Differencia(有序表线段树)
题意很直观,我就不说了。
解析:这是我以前没有接触过的线段树类型,有序表线段树,每个节点申请了两段空间,主要是为了保存左边儿子会有多少比v小的,右边儿子会有多少比v小
的,所以在建树过程中要归并排序。可能我讲起来比较难懂,详见代码,我给了注释。
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef __int64 LL;
#define e tree[id]
#define lson tree[id*2]
#define rson tree[id*2+1]
const int mod=1e9+;
const int maxn=;
const int C=~(<<),M=(<<)-;
int rnd(int last,int &a,int &b)
{
a=(+(last>>))*(a&M)+(a>>);
b=(+(last>>))*(b&M)+(b>>);
return (C&((a<<)+b))%;
}
int n,m,A,B,a[maxn],b[maxn],c[maxn],xs[maxn];
bool cmp(const int& x,const int& y){ return b[x]<b[y]; }
int data[maxn<<],*p;
int* New(int len){ p+=len; return p-len; } //静态的申请空间
void init() //离散化
{
for(int i=;i<n;i++) xs[i]=b[i];
sort(xs,xs+n);
for(int i=;i<n;i++) b[i]=upper_bound(xs,xs+n,b[i])-xs-;
for(int i=;i<n;i++) a[i]=upper_bound(xs,xs+n,a[i])-xs-;
p=data; //在最开始的位置
}
struct Tree
{
int le,ri,d,sum;
int *lid,*rid;
void Set(int v){ d=v; sum=v+; }
int GoLe(int v){ return v==-?v:lid[v]; } //左边有多少<=v的
int GoRi(int v){ return v==-?v:rid[v]; } //右边有多少<=v的
}tree[*maxn];
void pushup(int id){ e.sum=lson.sum+rson.sum; } //取和
void pushdown(int id)
{
if(e.d!=-) //延迟更新
{
lson.Set(e.GoLe(e.d));
rson.Set(e.GoRi(e.d));
e.d=-;
}
}
void Build_tree(int id,int le,int ri)
{
e.le=le,e.ri=ri,e.d=-;
e.lid=New(ri-le+); //左右都要申请空间
e.rid=New(ri-le+);
if(le==ri){ e.sum=(a[le]>=b[le]); return; }
int mid=(le+ri)/;
Build_tree(id*,le,mid);
Build_tree(id*+,mid+,ri);
pushup(id);
int ll=mid-le+,rl=ri-mid;
int *vl=b+le,*vr=b+mid+;
int i=,j=,cnt=;
while(i<ll&&j<rl) //归并排序
{
if(vl[i]<vr[j]) //左边小于右边
{
e.lid[cnt]=i;
e.rid[cnt]=j-;
c[cnt++]=vl[i++];
}
else
{
e.lid[cnt]=i-;
e.rid[cnt]=j;
c[cnt++]=vr[j++];
}
}
while(i<ll) //左边没完的
{
e.lid[cnt]=i;
e.rid[cnt]=j-;
c[cnt++]=vl[i++];
}
while(j<rl) //右边没完的
{
e.lid[cnt]=i-;
e.rid[cnt]=j;
c[cnt++]=vr[j++];
}
int k=;
for(int i=le;i<=ri;i++) b[i]=c[k++];
}
void Update(int id,int x,int y,int v) //更新
{
int le=e.le,ri=e.ri;
if(x<=le&&ri<=y){ e.Set(v); return; } //在区间内
pushdown(id);
int mid=(le+ri)/;
if(x<=mid) Update(id*,x,y,e.GoLe(v)); //左边GoLe代表左边有多少<=v的
if(y>mid) Update(id*+,x,y,e.GoRi(v));//右边同理
pushup(id);
}
int Query(int id,int x,int y) //查询
{
int le=e.le,ri=e.ri;
if(x<=le&&ri<=y) return e.sum; //在区间内直接返回值
pushdown(id); //延迟更新
int mid=(le+ri)/;
int ret=;
if(x<=mid) ret+=Query(id*,x,y); //加上左边
if(y>mid) ret+=Query(id*+,x,y); //加上右边
return ret;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&n,&m,&A,&B);
for(int i=;i<n;i++) scanf("%d",&a[i]); //输入
for(int i=;i<n;i++) scanf("%d",&b[i]);
init();
Build_tree(,,n-); //建树
int last=,ret=;
for(int i=;i<=m;i++)
{
int l=rnd(last,A,B)%n;
int r=rnd(last,A,B)%n;
int x=rnd(last,A,B)+;
if(l>r) swap(l,r);
if((l+r+x)%) //为奇数是插入
{
x=upper_bound(xs,xs+n,x)-xs-;
Update(,l,r,x);
}
else //否则查询
{
last=Query(,l,r);
ret=(ret+(LL)i*last%mod)%mod;
}
}
printf("%d\n",ret);
}
return ;
}
Hdu5737-Differencia(有序表线段树)的更多相关文章
- 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径
51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...
- 51nod 1593 公园晨跑 | ST表(线段树?)思维题
51nod 1593 公园晨跑 有一只猴子,他生活在一个环形的公园里.有n棵树围绕着公园.第i棵树和第i+1棵树之间的距离是 di ,而第n棵树和第一棵树之间的距离是 dn .第i棵树的高度是 hi ...
- Glad You Came hdu-6356(ST表 || 线段树)
第一种用线段树,用两颗数维护区间最大值和区间的最小值,然后更新的时候如果我目前区间内的最大值比我得到的v小,那么我就把这个区间修改成v,如果我的最小值比v大,那么v就是没有用的,直接跳过,然后这样每次 ...
- Codeforces 487B Strip (ST表+线段树维护DP 或 单调队列优化DP)
题目链接 Strip 题意 把一个数列分成连续的$k$段,要求满足每一段内的元素最大值和最小值的差值不超过$s$, 同时每一段内的元素个数要大于等于$l$, 求$k$的最小值. 考虑$DP$ 设$ ...
- bzoj 1699: [Usaco2007 Jan]Balanced Lineup排队【st表||线段树】
要求区间取min和max,可以用st表或线段树维护 st表 #include<iostream> #include<cstdio> using namespace std; c ...
- (DP ST表 线段树)51NOD 1174 区间中最大的数
给出一个有N个数的序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中,最大的数是多少. 例如: 1 7 6 3 1.i = 1, j = 3,对应的数为7 6 3,最大的数为7. ...
- [luoguP1816] 忠诚(st表 || 线段树)
传送门 其实我就是想练练 st表 本以为学了线段树可以省点事不学 st表 了 但是后缀数组中用 st表 貌似很方便 所以还是学了吧,反正也不难 ——代码 #include <cstdio> ...
- RMQ--树状数组,ST表,线段树
RMQ Range Minimum/Maximum Query 区间最值问题 树状数组 https://www.cnblogs.com/xenny/p/9739600.html lowbit(x) x ...
- The 2019 ICPC China Nanchang National Invitational and International Silk-Road Programming Contest - F.Sequence(打表+线段树)
题意:给你一个长度为$n$的数组,定义函数$f(l,r)=a_{l} \oplus a_{l+1} \oplus...\oplus a_{r}$,$F(l,r)=f(l,l)\oplus f(l,l+ ...
随机推荐
- Raid1源代码分析--初始化流程
初始化流程代码量比较少,也比较简单.主要是run函数.(我阅读的代码的linux内核版本是2.6.32.61) 四.初始化流程分析 run函数顾名思义,很简单这就是在RAID1开始运行时调用,进行一些 ...
- centos无线网卡设置
联想thinkpad E430 ,安装上centos后,无线网卡一直无法使用,经历了艰苦曲折到网卡驱动安装过程,历时2个晚上终于开心到用上无线网卡. 1.查看无线网卡到具体型号 [root@local ...
- jQuery----blur()方法
当元素失去焦点时发生 blur 事件. blur() 函数触发 blur 事件,或者如果设置了 function 参数,该函数也可规定当发生 blur 事件时执行的代码. 提示:早前,blur 事件仅 ...
- Arcgis for js载入天地图
综述:本节讲述的是用Arcgis for js载入天地图的切片资源. 天地图的切片地图能够通过esri.layers.TiledMapServiceLayer来载入.在此将之进行了一定的封装,例如以下 ...
- Hadoop动态加入/删除节点(datanode和tacktracker)
大体,正确的做法是首选的配置文件,然后开始详细机对应的进程/停止操作. 网上一些资料说在调整配置文件的时候,优先使用主机名而不是IP进行配置. 总的来说加入/删除DataNode和TaskTracke ...
- ORACLE触发器概述之【行触发器】【weber出品】
1. 行触发器的定义 行触发器是指执行DML操作时,每作用一行就触发一次的触发器.审计数据变化时,可以使用行触发器 2. 建立行触发器的语法如下: create or replace trigger ...
- .Net调用Office Com组件的原理及问题检索com类工厂组件检索 COM 类工厂中 CLSID 为 {XXX} 的组件失败
我是在本地32位操作系统+vs2010+office2007做创建并下载Excel,ppt文件的操作没有问题,发布到64位系统的服务器上报错,最开始报错:: 1:Retrieving the COM ...
- iOS横竖屏
现在开发的APP大部分界面是竖屏的,只有视频播放的界面和webview阅读文字的界面是可以横屏操作的. 那么就进行如下处理: 1.首先确保APP支持横屏旋转 2.我的App里面都是走UINavigat ...
- Java图片工具类,完成图片的截取和任意缩放
package com.common.util; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Renderin ...
- 把python项目部署到centos里
.安装centos VMware9下面安装centos .在centos下面设置共享文件夹为你本地的论坛的代码,然后设置网络为桥接:直接连接到物理网络,赋值网络连接状态 .进入forum_svr.py ...