hdu5737
首先思考一个朴素的做法
将b[]维护成一个线段树套有序表,每次修改a[]用线段树+lazy tag
并在线段树的子区间上在有序表中二分更新这段区间中a[i]>=b[i]的值,复杂度O(nlog^2)
有没有更优的做法?
考虑在一次修改操作中,查询的数是相同的,并且b[]这个有序表始终不变
因此在生成b[]的线段树套有序表过程中(其实就是归并排序的记录)
我们维护每个数在左右子区间中名次。
这样修改的时候我们只要对b[]排好序的整体做一次二分,找到b[m]<=x<b[m+1]
把修改成x当作修改成b[m],这样我们就能O(1)地更新每个子区间的计数,问题得解
#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
const int mo=;
vector< pair<int,int> > tr[*];
int laz[*],s[*],a[],b[],c[];
int A,B,n,m,t;
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)) % ;
} void build(int i,int l,int r)
{
laz[i]=-;
tr[i].clear();
if (l==r)
{
s[i]=(a[l]>=b[l]);
}
else {
int m=(l+r)>>;
build(i*,l,m);
build(i*+,m+,r);
s[i]=s[i*]+s[i*+];
int x=l,y=m+,h=l;
while (x<=m&&y<=r)
{
if (b[x]<b[y])
{
tr[i].push_back(mp(x-l,y-m-));
c[h++]=b[x++];
}
else {
tr[i].push_back(mp(x-l-,y-m-));
c[h++]=b[y++];
}
}
while (x<=m)
{
tr[i].push_back(mp(x-l,r-m-));
c[h++]=b[x++];
}
while (y<=r)
{
tr[i].push_back(mp(m-l,y-m-));
c[h++]=b[y++];
}
for (int k=l; k<=r; k++) b[k]=c[k];
}
} void push(int i)
{
int x=laz[i];
laz[i*]=(x==-)?-:tr[i][x].first;
laz[i*+]=(x==-)?-:tr[i][x].second;
s[i*]=laz[i*]+;
s[i*+]=laz[i*+]+;
laz[i]=-;
} void add(int i,int l,int r,int x,int y,int w)
{
if (x<=l&&y>=r)
{
laz[i]=w;
s[i]=w+;
}
else {
int m=(l+r)>>;
if (laz[i]>-) push(i);
if (x<=m) add(i*,l,m,x,y,w==-?w:tr[i][w].first);
if (y>m) add(i*+,m+,r,x,y,w==-?w:tr[i][w].second);
s[i]=s[i*]+s[i*+];
}
} int ask(int i,int l,int r,int x,int y)
{
if (x<=l&&y>=r) return s[i];
else {
int m=(l+r)>>,ans=;
if (laz[i]>-) push(i);
if (x<=m) ans+=ask(i*,l,m,x,y);
if (y>m) ans+=ask(i*+,m+,r,x,y);
return ans;
}
} int main()
{
int cas;
scanf("%d",&cas);
while (cas--)
{
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]);
b[n+]=;
build(,,n);
int ans=;
int last=;
for (int i=; i<=m; i++)
{
int l=rnd(last,A,B)%n+,r=rnd(last,A,B)%n+,x=rnd(last,A,B)+;
if (l>r) swap(l,r);
if ((l+r+x)%==)
{
last=ask(,,n,l,r);
ans=(ans+1ll*i*last%mo)%mo;
}
else {
int w=upper_bound(b+,b++n,x)-b-;
add(,,n,l,r,w);
}
}
printf("%d\n",ans);
}
}
hdu5737的更多相关文章
- hdu5737(2016多校联赛第2场D)
题意:给2组数据a和b数组,每次有2种操作:(+,l,r,x)把a数组第l个到第r个元素全置为x,(?,l,r)查询[l,r]之间哪些位置满足a[i]>=b[i](i>=l &&a ...
- HDU5737 : Differencia
注意到$b$不变,考虑用归并树来维护这个$b$序列,对于每个节点有序地维护$b$,同时在归并的时候预处理出每个元素在左右儿子里的排名. 在归并树上额外维护区间内$a\geq b$的个数以及赋值标记. ...
随机推荐
- 关于debian配置的问题汇总
debian的apache多域名配置: https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-ho ...
- Pandoc中的Markdown语法
概述 Pandoc中支持扩展修订版本的Markdown语法 使用pandoc中支持的Markdown语法用 -f markdown 使用标准Markdown语法用 -f markdown_strict ...
- Spring 集成Quartz
在使用jdk的timer时发现无法在指定的日期进行执行任务.这便引入一个优秀的开源任务调度框架“quartz”.这里使用的是quartz-1.8.6版本.Quart的官网:http://www.qua ...
- 使用 URLDecoder 和 URLEncoder 对中文字符进行编码和解码
原文: https://blog.csdn.net/justloveyou_/article/details/57156039 使用 URLDecoder 和 URLEncoder 对中文字符进行编码 ...
- 文件格式转换神器-pandoc
By francis_hao Mar 11,2017 介绍 如果你需要在各种类型的文件中穿梭,那么你需要这把瑞士军刀-pandoc 它可以将各种常见的不常见的文件类型转换成另一种,我感兴趣的是在 ...
- debounce 与 throttle 区别
原文地址:http://undefinedblog.com/debounce-and-throttle/ 二.什么是debounce 1. 定义 如果用手指一直按住一个弹簧,它将不会弹起直到你松 ...
- NOIP2003 神经网络(bfs)
NOIP2003 神经网络 题目背景: 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别.函数逼近及贷款风险评估等诸多领域有广泛的应 ...
- MUI -- plus初始化原理及plus is not defined,mui is not defined 错误汇总
不要在没有plus和mui的环境下调用相关API 普通浏览器里没有plus环境,只有HBuilder真机运行和打包后才能运行plus api. 在普通浏览器里运行时plus api时控制台必然会输出p ...
- centos7装机时更改网卡名为eth0操作
- HDU5772 String problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission ...