[线段树] Jzoj P6293 迷宫

Description

 

题解

  • 用线段树维护区间[l,,r]中,m行格子左边第x行到右边第y行的距离
  • 合并两个的话,枚举中间点k,暴力转移

 

代码

 1 #pragma GCC optimize(2)
 2 #include <cstdio>
 3 #include <iostream>
 4 #include <cstring>
 5 using namespace std;
 6 const int N=7,M=200001,inf=0x3f3f3f3f;
 7 int n,m,q,a[N][M];
 8 struct tree{ int p[N][N]; }t[M*4];
 9 void pushup(int d)
10 {
11     memset(t[d].p,0x3f,sizeof(t[d].p));
12     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) t[d].p[i][k]=min(t[d].p[i][k],t[d*2].p[i][j]+t[d*2+1].p[j][k]);
13 } 
14 void build(int d,int l,int r) 
15 {
16     if (l==r) 
17     {
18         for (int i=1;i<=n;i++) t[d].p[i][i]=(a[i][l]==1?1:inf);
19         for (int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) 
20         {
21             int cnt=0;
22             for (int k=i;k<=j;k++) { if (a[k][l]==0) { cnt=inf; break; } cnt++; }
23             t[d].p[i][j]=t[d].p[j][i]=cnt;
24         }
25         return;
26     }
27     int mid=l+r>>1;
28     build(d*2,l,mid),build(d*2+1,mid+1,r),pushup(d);
29 }
30 void modify(int d,int l,int r,int pos)
31 {
32     if (l==r) 
33     {
34         for (int i=1;i<=n;i++) t[d].p[i][i]=(a[i][l]==1?1:inf);
35         for (int i=1;i<=n;i++) for (int j=i+1;j<=n;j++) 
36         {
37             int cnt=0;
38             for (int k=i;k<=j;k++) { if (a[k][l]==0) { cnt=inf;    break; } cnt++;    }
39             t[d].p[i][j]=t[d].p[j][i]=cnt;
40         }
41         return;
42     }
43     int mid=(l+r)>>1;
44     if (pos<=mid) modify(d*2,l,mid,pos);
45     if (pos>mid) modify(d*2+1,mid+1,r,pos);
46     pushup(d);
47 }
48 tree merge(tree t1,tree t2)
49 {
50     tree r;
51     memset(r.p,0x3f,sizeof r.p);
52     for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) for (int k=1;k<=n;k++) r.p[i][k]=min(r.p[i][k],t1.p[i][j]+t2.p[j][k]);
53     return r;
54 }
55 tree query(int d,int l,int r,int L,int R)
56 {
57     if (L==l&&r==R) return t[d];
58     int mid=(l+r)>>1;
59     if (L<=mid&&R>mid) return merge(query(d*2,l,mid,L,mid),query(d*2+1,mid+1,r,mid+1,R));
60     else if (R<=mid) return query(d*2,l,mid,L,R);
61     else if (L>mid) return query(d*2+1,mid+1,r,L,R);
62 }
63 int main()
64 {
65     freopen("maze.in","r",stdin),freopen("maze.out","w",stdout),scanf("%d%d%d",&n,&m,&q);
66     for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&a[i][j]);
67     build(1,1,m);
68     for (int x,y,X,Y,op;q;q--)
69     {
70         scanf("%d%d%d",&op,&x,&y);
71         if (op==1) a[x][y]^=1,modify(1,1,m,y); else 
72         {
73             scanf("%d%d",&X,&Y); tree ans=query(1,1,m,y,Y);
74             printf("%d\n",ans.p[x][X]==inf?-1:ans.p[x][X]-1);
75         }
76     }
77 }

 

posted @ 2019-08-12 21:19  BEYang_Z  阅读(240)  评论(0编辑  收藏  举报