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$的个数以及赋值标记. ...
随机推荐
- redis-20180118
1.redis hash 100% 2.redis list 100% 3.redis sentinel 20%
- 【bzoj3940】[Usaco2015 Feb]Censoring AC自动机
题目描述 Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they h ...
- Web.config配置文件中的属性add,key,value含义
这是添加自定义字符串的方式,保存是以键-值的形式保存的,可以通过key获取value,一般用这种方法配置全局内使用的字符串. <configuration>是配置文件的根配置节. < ...
- hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)
Cyclic Tour Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)Total ...
- count(1)与count(*)
http://www.cnblogs.com/sueris/p/6650301.html 结论:实际项目中count(1)用到多 记得很早以前就有人跟我说过,在使用count的时候要用count(1) ...
- Install the Active Directory Administration Tools on Windows Server
安装 Active Directory 管理工具 To manage your directory from an EC2 Windows instance, you need to install ...
- bootstrap再次回顾认识到的东西
1,需要使用html5文档类型(Doctype),因此在使用bootstrap项目的开头包含下面的代码段. <!DOCTYPE html> <html> ....... < ...
- POJ 3070 + 51Nod 1242 大斐波那契数取余
POJ 3070 #include "iostream" #include "cstdio" using namespace std; class matrix ...
- HDU 2084 DP经典例子---数塔问题
http://acm.hdu.edu.cn/showproblem.php?pid=2084 #include "iostream" #include "cstdio&q ...
- 最适合初学者学习的idea教程
https://github.com/judasn/IntelliJ-IDEA-Tutorial