首先思考一个朴素的做法

将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);
}
}

最新文章

  1. PHPnow在win8下安装失败的解决办法
  2. JavaWeb的学习之Servlet(转载自孤傲苍狼)
  3. codeforces 446B(优先队列)
  4. C#设计模式(8)——桥接模式(Bridge Pattern)
  5. STM32F0xx_DAC输出电压配置详细过程
  6. SqlServer高版本数据本分还原到低版本方法
  7. 记录一次centos升级gblic的教训
  8. iOS UI布局调试工具
  9. HDU 4643 GSM 简单计算几何
  10. J2EE的13个规范之JDBC
  11. SD卡FAT32获得高速的文件格式(图文介绍)
  12. ggplot2 scale相关设置2—时间设置
  13. vue之nextTick全面解析
  14. git reset揭秘
  15. AbstractQueuedSynchronizer原理及代码分析
  16. 阿里云消息队列的C#使用http接口发送消息实例
  17. PMP:9.项目资源管理
  18. Python_匿名函数
  19. JPA唯一索引更新删除的问题
  20. HTML5 元素拖拽实现 及 jquery.event.drag插件

热门文章

  1. TCP/IP Note2
  2. 周记【距gdoi:91天】
  3. 一个JavaScript日期格式化扩展函数
  4. ubuntu下opencv使用cvNamedWindow()和cvShowImage()出错的解决方法
  5. fastjson解析服务端返回的数据
  6. There is an overlap in the region chain
  7. Drac6-Web界面无法访问
  8. (转)Django常用命令
  9. tomcat编码配置
  10. ACM-ICPC 2018 南京赛区网络预赛 Sum