Description
给定序列A[]和B[],记C[i]=max(C[i-1],A[i]),要求资瓷两个操作:
- 0 x y,改A[x]为y
- 1 x y,改B[x]为y
每次操作输出
∏
i
=
1
n
m
i
n
(
B
i
,
C
i
)
\prod\limits_{i=1}^{n}{min(B_i,C_i)}
i=1∏nmin(Bi,Ci)
n
≤
1
0
5
n\le 10^5
n≤105,保证
y
≥
A
x
y\ge A_x
y≥Ax
Solution
很套路的题目,细节比较多而且很繁琐。感觉自己码力不太行了
别人都写3k我写5k系列
可以发现A[i]是不减的,那么我们就可以算出它作为前缀最大值的最长区间[L,R],于是这一整段区间的C都是一样的了
观察可以发现,这些最大值的区间互不相交,且随着我们的操作,它们的数量是不增的。那么我们就可以暴力把[L,R]之间的区间贡献都除掉,然后乘上[L,R]的答案
考虑一整段区间的B[]和某个固定的C取min后乘积,显然比C小的都是它们本身,比C大的我们只需要统计多少个就能快速幂了。这就是一个带修改二维数点问题,上树套树就ojbk
预处理的话,单点修改+区间最大值可以线段树,注意到这实际上是前缀最大值因此可以树状数组。记录某个位置最右边界R[i]可以区间修改+单点查询线段树。我比较喜欢线段树所以写了很多棵线段树(滑稽
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define lowbit(x) (x&-x)
typedef long long LL;
const int INF=0x3f3f3f3f;
const int MOD=1000000007;
const int N=200005;
struct treeNode {
int l,r;
LL prod,cnt;
} t[N*175];
int rt[N],max[N<<2],R[N<<2],RR[N<<2],n,m,tot;
LL a[N],b[N],w[N],inv,ans;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
LL ksm(LL x,LL dep) {
LL res=1;
for (;dep;dep>>=1) {
(dep&1)?(res=res*x%MOD):0;
x=x*x%MOD;
}
return res;
}
void modify(int &now,int tl,int tr,LL x,int v) {
if (!now) t[now=++tot].prod=1;
t[now].cnt+=v;
if (v==-1) t[now].prod=t[now].prod*inv%MOD;
else t[now].prod=t[now].prod*x%MOD;
if (tl==tr) return ;
int mid=(tl+tr)>>1;
if (x<=mid) modify(t[now].l,tl,mid,x,v);
else modify(t[now].r,mid+1,tr,x,v);
}
void ins(int x,int pos,int v) {
for (;x<=n;x+=lowbit(x)) modify(rt[x],1,INF,pos,v);
}
int count(int now,int tl,int tr,int l,int r) {
if (!now) return 0;
if (tl>=l&&tr<=r) return t[now].cnt;
int mid=(tl+tr)>>1,res=0;
if (l<=mid) res+=count(t[now].l,tl,mid,l,r);
if (mid+1<=r) res+=count(t[now].r,mid+1,tr,l,r);
return res;
}
LL mul(int now,int tl,int tr,int l,int r) {
if (!now) return 1;
if (tl>=l&&tr<=r) return t[now].prod;
int mid=(tl+tr)>>1; LL res=1;
if (l<=mid) res=res*mul(t[now].l,tl,mid,l,r)%MOD;
if (mid+1<=r) res=res*mul(t[now].r,mid+1,tr,l,r)%MOD;
return res;
}
LL askc(int x,int l,int r) {
LL res=0;
for (;x;x-=lowbit(x)) res+=count(rt[x],1,INF,l,r);
return res;
}
LL askm(int x,int l,int r) {
LL res=1;
for (;x;x-=lowbit(x)) res=res*mul(rt[x],1,INF,l,r)%MOD;
return res;
}
int query_max(int now,int tl,int tr,int l,int r) {
if (r<l) return 0;
if (tl>=l&&tr<=r) return max[now];
int mid=(tl+tr)>>1,qx=0,qy=0;
if (l<=mid) qx=query_max(now<<1,tl,mid,l,r);
if (mid+1<=r) qy=query_max(now<<1|1,mid+1,tr,l,r);
return std:: max(qx,qy);
}
void change(int now,int tl,int tr,int x,int v) {
if (tl==tr) return (void) (max[now]=v);
int mid=(tl+tr)>>1;
if (x<=mid) change(now<<1,tl,mid,x,v);
else change(now<<1|1,mid+1,tr,x,v);
max[now]=std:: max(max[now<<1],max[now<<1|1]);
}
void right(int now,int tl,int tr,int l,int r,int v) {
if (tl>=l&&tr<=r) return (void) (R[now]=RR[now]=v);
if (RR[now]) {
RR[now<<1]=RR[now<<1|1]=RR[now];
R[now<<1]=R[now<<1|1]=RR[now]; RR[now]=0;
}
int mid=(tl+tr)>>1;
if (l<=mid) right(now<<1,tl,mid,l,r,v);
if (mid+1<=r) right(now<<1|1,mid+1,tr,l,r,v);
}
int get_right(int now,int tl,int tr,int x) {
if (tl==tr) return R[now];
if (RR[now]) {
RR[now<<1]=RR[now<<1|1]=RR[now];
R[now<<1]=R[now<<1|1]=RR[now]; RR[now]=0;
}
int mid=(tl+tr)>>1;
if (x<=mid) return get_right(now<<1,tl,mid,x);
else return get_right(now<<1|1,mid+1,tr,x);
}
LL calc(int l,int r,LL c) {
LL res1=askm(r,1,c);
LL tmp=askm(l-1,1,c);
tmp=ksm(tmp,MOD-2);
res1=res1*tmp%MOD;
LL res2=askc(r,c+1,INF)-askc(l-1,c+1,INF);
res2=ksm(c,res2);
return res1*res2%MOD;
}
void solve(int l,int r,int x,LL c) {
int tl=1,tr=l,res=l,wjp=get_right(1,1,n,l);
while (tl<=tr) {
int mid=(tl+tr)>>1;
if (get_right(1,1,n,mid)==wjp) tr=mid-1,res=mid;
else tl=mid+1;
}
if (res<=l-1) {
right(1,1,n,res,l-1,l-1);
w[l-1]=w[wjp];
}
int now=l;
while (now<=r) {
int rig=get_right(1,1,n,now);
rig=std:: min(r,rig);
LL tmp=calc(now,rig,w[rig]);
tmp=ksm(tmp,MOD-2);
ans=ans*tmp%MOD;
now=rig+1;
}
right(1,1,n,l,r,r); w[r]=c;
ans=ans*calc(l,r,c)%MOD;
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
n=read(),m=read();
rep(i,1,n) a[i]=read();
rep(i,1,n) b[i]=read();
LL mx=0,last=0; ans=1;
rep(i,1,n) {
change(1,1,n,i,a[i]);
if (a[i]>mx) {
if (last) right(1,1,n,last,i-1,i-1);
w[i-1]=mx;
mx=a[i];
last=i;
}
ans=ans*std:: min(mx,b[i])%MOD;
ins(i,b[i],1);
}
right(1,1,n,last,n,n); w[n]=mx;
for (;m--;) {
int opt=read(),x=read(),y=read();
if (opt==0) {
int mm=query_max(1,1,n,1,x-1);
if (mm<y) {
int l=x,r=n,res=x;
while (l<=r) {
int mid=(l+r)>>1;
if (query_max(1,1,n,x+1,mid)>=y) r=mid-1;
else l=mid+1,res=mid;
}
solve(x,res,x,y);
}
change(1,1,n,x,y); a[x]=y;
} else {
int rr=get_right(1,1,n,x);
LL tmp=std:: min(1LL*w[rr],b[x]);
tmp=ksm(tmp,MOD-2);
ans=ans*tmp%MOD;
ans=ans*std:: min(1LL*y,1LL*w[rr])%MOD;
inv=ksm(b[x],MOD-2);
ins(x,b[x],-1);
b[x]=y;
ins(x,b[x],1);
}
printf("%lld\n", ans);
}
return 0;
}