[线段树][快速幂][循环节] Jzoj P6278 跳房子

Description

Input

Output

Sample Input

4 4
1 2 9 3
3 5 4 8
4 3 2 7
5 8 1 6
4
move 1
move 1
change 1 4 100
move 1 

Sample Output

4 2
1 3
1 4 

Data Constraint

 

 

题解

  • 我们可以考虑用线段树来做,我们记录对于每一列,在每一行其向下一列会走到哪
  • 这样的话每一列都建立了一个置换,之后我们只要把他们全部合并起来
  • 在行走的时候,如果步数够得话就直接走循环节,否则一步一步走就可以
  • 修改操作的话,我们只用修改当前点的左上、左和左下就行了,它只对这些点有贡献

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define N 2010
 5 using namespace std;
 6 int n,m,Q,px,py,a[N][N];
 7 char s[10];
 8 struct node 
 9 {
10     int p[N];
11     node () { for (int i=1;i<=n;i++) p[i]=i; }
12     node operator * (const node &b) const { node a; for (int i=1;i<=n;i++) a.p[i]=b.p[p[i]]; return a; }
13 }w[N],t[N*4];
14 node ksm(node a,int b) { node r; for (;b;b>>=1,a=a*a) if (b&1) r=r*a; return r; }
15 int pos(int x,bool y) { return (x==(y?m+1:n+1))?1:(!x?(y?m:n):x); }
16 void change(int x,int y)
17 {
18     int r=0; x=pos(x,0),y=pos(y,1);
19     for (int i=-1;i<=1;i++)
20     {
21         int xx=pos(i+x,0),yy=pos(1+y,1);
22         if (r<a[xx][yy]) r=a[xx][yy],w[y].p[x]=xx;
23     }
24 }
25 void build(int d,int l,int r)
26 {
27     if (l==r) { t[d]=w[l]; return; }
28     int mid=l+r>>1;
29     build(d*2,l,mid),build(d*2+1,mid+1,r),t[d]=t[d*2]*t[d*2+1];
30 }
31 void modify(int d,int l,int r,int x)
32 {
33     if (l==r) { t[d]=w[x]; return; }
34     int mid=l+r>>1;
35     if (x<=mid) modify(d*2,l,mid,x); else modify(d*2+1,mid+1,r,x);
36     t[d]=t[d*2]*t[d*2+1];
37 }
38 void move(int &x,int &y,int k){ while (k--) x=w[y].p[x],y=pos(y+1,1); }
39 int main()
40 {
41     freopen("jump.in","r",stdin),freopen("jump.out","w",stdout),scanf("%d%d",&n,&m);
42     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
43     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) change(i,j);
44     build(1,1,m),scanf("%d",&Q),px=py=1;
45     for (int x,y,z,len;Q;Q--)
46     {
47         scanf("%s",s);
48         if (s[0]=='m')
49         {
50             scanf("%d",&x),len=min(x,m-py+1),move(px,py,len),x-=len;
51             if (x) px=ksm(t[1],x/m).p[px],x%=m,move(px,py,x);
52             printf("%d %d\n",px,py);
53         }
54         else scanf("%d%d%d",&x,&y,&z),a[x][y]=z,change(x-1,y-1),change(x,y-1),change(x+1,y-1),modify(1,1,m,pos(y-1,1));
55     }
56 }

 

posted @ 2019-08-06 10:47  BEYang_Z  阅读(421)  评论(0编辑  收藏  举报