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+ ...
随机推荐
- POJ 3378
题目链接 查找长度为5的上升序列总数 用的树状数组+高精度 用树状数组求在i前面比i小的数有几个 用的4个树状数组,A[i][j]表示长度为i的以j为结尾的个数,A[i][j]=A[i-1][1... ...
- Mac OS X 下修改网卡地址和抵御 ARP 攻击
用 Mac 系统有一段时间了,这里记录一下自己遇到的需要终端命令解决的问题. 网络环境绑定了原先机器的 MAC 地址,由于特殊原因,先把新机器的网卡地址改成原先那台. 在终端输入sudo ifconf ...
- Unity 3D 动画帧事件
前几天在项目开发中碰到一个这样的需求,RPG游戏中,特效和动画播放不同步的.假如主角在攻击NPC时,先实例化特效,后播放动画.动画毕竟是有一个时间长度的.等到动画播放攻击挥刀的那一瞬间时,特效可能早就 ...
- andorid 开发笔记 -- 问题与解决
1. SQLiteDataBase 中 TimeStamp 转化为 Date 的问题:java.text.ParseException: Unparseable date: "Sun Jan ...
- jQuery.extend 和 jQuery.fn.extend
1.jQuery.extend 我们先把jQuery看成了一个类,这样好理解一些.jQuery.extend(),是扩展的jQuery这个类. 假设我们把jQuery这个类看成是人类,能吃饭能喝水能跑 ...
- Asp.net中实现同一用户名同时登陆,注销先前用户(转)
Web 项目中经常遇到的问题就是同一用户名多次登陆的问题,相应的解决办法也很多,总结起来不外乎这几种解决办法:将登陆后的用户名放到数据库表中:登陆后的用 户名放到Session中:登陆后的用户名放到A ...
- 学习MVC框架之一
一.MVC的概述 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑和数据显示分离的 ...
- 如何在Silverlight应用程序中获取ASP.NET页面参数
asp.net Silverlight应用程序中获取载体aspx页面参数 有时候SL应用中需要使用由aspx页面中传递过来的参数值,此时通常有两种方法获取 1. 使用InitParameters属性, ...
- 浅谈Windows Server APPFABRIC
hi,everyone !真的是好久好久没有update blog了,因为最近忙着备考,没有时间对<数据结构与算法>进行研究学习了.所以,blog一直未更新.today is Friday ...
- (搬运工)国内顺利使用Google的另类技巧
在特殊的地方和特殊的时间,流畅顺利使用Google的方法也会变得很特殊.分享一些奇葩的Google使用方法,通过下列网址也可以使用Google来搜索:http://www.GoogleStable.c ...