首先思考一个朴素的做法

将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的更多相关文章

  1. 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 ...

  2. HDU5737 : Differencia

    注意到$b$不变,考虑用归并树来维护这个$b$序列,对于每个节点有序地维护$b$,同时在归并的时候预处理出每个元素在左右儿子里的排名. 在归并树上额外维护区间内$a\geq b$的个数以及赋值标记. ...

随机推荐

  1. redis-20180118

    1.redis hash  100% 2.redis list 100% 3.redis sentinel 20%

  2. 【bzoj3940】[Usaco2015 Feb]Censoring AC自动机

    题目描述 Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they h ...

  3. Web.config配置文件中的属性add,key,value含义

    这是添加自定义字符串的方式,保存是以键-值的形式保存的,可以通过key获取value,一般用这种方法配置全局内使用的字符串. <configuration>是配置文件的根配置节. < ...

  4. hdu 1853 Cyclic Tour (二分匹配KM最小权值 或 最小费用最大流)

    Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)Total ...

  5. count(1)与count(*)

    http://www.cnblogs.com/sueris/p/6650301.html 结论:实际项目中count(1)用到多 记得很早以前就有人跟我说过,在使用count的时候要用count(1) ...

  6. Install the Active Directory Administration Tools on Windows Server

    安装 Active Directory 管理工具 To manage your directory from an EC2 Windows instance, you need to install ...

  7. bootstrap再次回顾认识到的东西

    1,需要使用html5文档类型(Doctype),因此在使用bootstrap项目的开头包含下面的代码段. <!DOCTYPE html> <html> ....... < ...

  8. POJ 3070 + 51Nod 1242 大斐波那契数取余

    POJ 3070 #include "iostream" #include "cstdio" using namespace std; class matrix ...

  9. HDU 2084 DP经典例子---数塔问题

    http://acm.hdu.edu.cn/showproblem.php?pid=2084 #include "iostream" #include "cstdio&q ...

  10. 最适合初学者学习的idea教程

    https://github.com/judasn/IntelliJ-IDEA-Tutorial