- 一个(n imes m)的循环矩阵,每个位置上有一个互不相同的权值。
- 每次会走到右、右上、右下中权值最大的格子。
- 初始在((1,1)),(q)次操作,分为两种:从当前位置出发走(k)步,并输出到达的位置;修改某个格子上的权值。
- (n,mle2000,qle5000,kle10^9)
倍增
(k)这么大一看就是倍增。
但我们显然不可能对每个位置都倍增预处理一遍,因为一次修改影响范围可能非常广。
考虑到(n,m,q)都非常小,实际上我们可以先暴力走到第一列,记(f_{i,j})表示从((i,1))出发走(2^j)轮后会走到((f_{i,j},1)),倍增后再暴力走完余数部分即可。
这样一来要倍增的位置只有(n)个,即便一次修改使得它们全部发生变化都没关系。
线段树
对于线段树上一个区间([l,r])开一个数组(v[rt][i]),表示从((i,l))出发会走到((v_i,r))。
合并的时候先求出((v[lc][i],mid))下一步会走到的位置((w,mid+1)),那么(v[rt][i]=v[rc][w])。
那么((v[1][i],m))下一步会走到的位置就是((f[i][0],1))了。
代码:(O(nqlogn))
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 2000
#define pre(x) (x^1?x-1:n)
#define nxt(x) (x^n?x+1:1)
using namespace std;
int n,m,a[N+5][N+5],f[N+5][31];
I int Q(CI x,CI y)//询问(x,y)下一个位置的行号
{
RI tx=x,ty=y^m?y+1:1;return a[pre(x)][ty]>a[tx][ty]&&(tx=pre(x)),a[nxt(x)][ty]>a[tx][ty]&&(tx=nxt(x)),tx;
}
class SegmentTree
{
private:
#define PT CI l=1,CI r=m,CI rt=1
#define LT l,mid,rt<<1
#define RT mid+1,r,rt<<1|1
int V[N<<2][N+5];I void PU(CI rt,CI mid) {for(RI i=1;i<=n;++i) V[rt][i]=V[rt<<1|1][Q(V[rt<<1][i],mid)];}//合并
public:
I void Bd(PT)//建树
{
if(l==r) {for(RI i=1;i<=n;++i) V[rt][i]=i;return;}RI mid=l+r>>1;Bd(LT),Bd(RT),PU(rt,mid);
}
I void U(CI y,PT)//更新
{
if(l==r) return;RI mid=l+r>>1;y<=mid?U(y,LT):U(y,RT),PU(rt,mid);
}
I void Get()//倍增预处理
{
RI i,j;for(i=1;i<=n;++i) f[i][0]=Q(V[1][i],m);for(j=1;j<=30;++j) for(i=1;i<=n;++i) f[i][j]=f[f[i][j-1]][j-1];
}
}S;
int main()
{
RI i,j;for(scanf("%d%d",&n,&m),i=1;i<=n;++i) for(j=1;j<=m;++j) scanf("%d",&a[i][j]);S.Bd(),S.Get();
RI Qt,px=1,py=1,x,y,k,t;char s[10];scanf("%d",&Qt);W(Qt--)
{
if(scanf("%s",s),s[0]=='c') {scanf("%d%d%d",&x,&y,&k),a[x][y]=k,S.U(y^1?y-1:m),S.Get();continue;}//直接修改,然后更新
scanf("%d",&k);W(k&&py^1) px=Q(px,py),++py>m&&(py=1),--k;t=k/m,k%=m;//暴力走到第一列
for(i=0;i<=30;++i) t>>i&1&&(px=f[px][i]);W(k) px=Q(px,py),++py>m&&(py=1),--k;printf("%d %d
",px,py);//倍增后暴力走余数
}return 0;
}