题目大意
解题思路
先考虑询问怎么做。
一个很关键的想法是,我们可以把操作了[l,r]的
ak
a
k
表示成一段区间的最大值,如果知道了这个区间,问题就很简单了。假设为max{a[le..ri]}
假设有一个假如我们有一个(l,r,k),我们怎么知道le和ri呢?
注意描述中带下标的l,r和不带下标的不是同一个东西。
我们从r开始,找到尽量晚的,能够覆盖k的区间,假设为
[li,ri]
[
l
i
,
r
i
]
,然后我们再找尽量大的j,使得
li∈[lj,rj],j<i
l
i
∈
[
l
j
,
r
j
]
,
j
<
i
。同样对
ri
r
i
找一个j’,然后再用j找到类似的
j2和j′2
j
2
和
j
2
′
,直到小于询问的l为止。当然小于的那个不要,左右两边扩展的次数也不一定一样。那么就找到了le和ri。
考虑优化这一过程,弄一颗“左树”一颗“右树”,一个点代表某个区间。左树中,一个点i的父亲指向j。(类似于上面的定义)右树类似。那么我们可以倍增找。
怎么找到尽量大的j?线段树区间打标记,单点查询。
那么你把询问离线挂在各自的r上面就好了。预处理出le和ri
剩下的问题就是区间最大值查询和单点修改了。
时间复杂度O(nlogn)
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
typedef double db;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
#define cmax(a,b) (a=(a>b)?a:b)
#define cmin(a,b) (a=(a<b)?a:b)*
const int N=1e5+5,M=4e5+5,mo=1e9+7,rt=3;
struct rec
{
int ka,x,y,z;
}qu[N];
int tr[M],tag[M],d[N],n,m,q,x,y,z,le[N],ri[N],Le[N],Ri[N],Log[N],i,a[N],l,lf[20][N],rf[20][N],j;
bool cmp(int a,int b)
{
return qu[a].y<qu[b].y;
}
int read()
{
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9')
{
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void down(int x,int bot)
{
if (!tag[x]) return ;
tr[x]=tag[x];
if (!bot) tag[x*2]=tag[x*2+1]=tag[x];
tag[x]=0;
}
void change(int x,int l,int r,int i,int j,int v)
{
if (l==i&&r==j)
{
tag[x]=v;
down(x,l==r);
return ;
}
int m=l+r>>1;
down(x*2,l==m);
down(x*2+1,m+1==r);
if (j<=m) change(x*2,l,m,i,j,v);
else if (m<i) change(x*2+1,m+1,r,i,j,v);
else change(x*2,l,m,i,m,v),change(x*2+1,m+1,r,m+1,j,v);
tr[x]=max(tr[x*2],tr[x*2+1]);
}
int get(int x,int l,int r,int i,int j)
{
if (l==i&&r==j) return tr[x];
int m=l+r>>1;
down(x*2,l==m);
down(x*2+1,m+1==r);
if (j<=m) return get(x*2,l,m,i,j);
else if (m<i) return get(x*2+1,m+1,r,i,j);
else return max(get(x*2,l,m,i,m),get(x*2+1,m+1,r,m+1,j));
}
void clear(int x,int l,int r)
{
tr[x]=tag[x]=0;
if (l==r)
{
tr[x]=a[l];
return ;
}
int m=l+r>>1;
clear(x*2,l,m);
clear(x*2+1,m+1,r);
tr[x]=max(tr[x*2],tr[x*2+1]);
}
int main()
{
freopen("t7.in","r",stdin);
freopen("t7.out","w",stdout);
n=read();m=read();q=read();
fo(i,1,n) a[i]=read();
fo(i,1,m)
{
le[i]=read();
ri[i]=read();
}
fo(i,1,q)
{
qu[i].ka=read();
qu[i].x=read();
qu[i].y=read();
if (qu[i].ka==2) qu[i].z=read(),d[++d[0]]=i;
}
sort(d+1,d+1+d[0],cmp);
l=1;
fo(i,1,m) Log[i]=trunc(log(i)/log(2));
fo(i,1,m)
{
lf[0][i]=get(1,1,n,le[i],le[i]);
rf[0][i]=get(1,1,n,ri[i],ri[i]);
fo(j,1,Log[m]) lf[j][i]=lf[j-1][lf[j-1][i]],rf[j][i]=rf[j-1][rf[j-1][i]];
change(1,1,n,le[i],ri[i],i);
while (qu[d[l]].y==i)
{
x=d[l];
z=get(1,1,n,qu[x].z,qu[x].z);
if (z<qu[x].x) z=0;
y=z;
fd(j,Log[m],0) if (lf[j][y]>=qu[x].x) y=lf[j][y];
Le[x]=le[y];
y=z;
fd(j,Log[m],0) if (rf[j][y]>=qu[x].x) y=rf[j][y];
Ri[x]=ri[y];
if (!z) Le[x]=Ri[x]=qu[x].z;
l++;
}
}
clear(1,1,n);
fo(i,1,q)
if (qu[i].ka==1)
change(1,1,n,qu[i].x,qu[i].x,qu[i].y);
else
{
printf("%d\n",get(1,1,n,Le[i],Ri[i]));
}
}