DP+线段树维护矩阵(2019牛客暑期多校训练营(第二场))--MAZE

题意:https://ac.nowcoder.com/acm/contest/882/E

给你01矩阵,有两种操作:1是把一个位置0变1、1变0,2是问你从第一行i开始,到最后一行j有几种走法。你只能不能向上走而且不能往回走。

思路:

01矩阵里每一行可以用一个矩阵表示向下有几种走法,i行到j行的的走法就是各行的矩阵的乘积。用线段树维护即可。

线段树seg【1】的【x】【y】就是答案。

  1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0);
  2 #include <cstdio>//sprintf islower isupper
  3 #include <cstdlib>//malloc  exit strcat itoa system("cls")
  4 #include <iostream>//pair
  5 #include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin);
  6 #include <bitset>
  7 //#include <map>
  8 //#include<unordered_map>
  9 #include <vector>
 10 #include <stack>
 11 #include <set>
 12 #include <string.h>//strstr substr strcat
 13 #include <string>
 14 #include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9;
 15 #include <cmath>
 16 #include <deque>
 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
 18 #include <vector>//emplace_back
 19 //#include <math.h>
 20 #include <cassert>
 21 #include <iomanip>
 22 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor
 23 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare)
 24 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
 25 //******************
 26 clock_t __STRAT,__END;
 27 double __TOTALTIME;
 28 void _MS(){__STRAT=clock();}
 29 void _ME(){__END=clock();__TOTALTIME=(double)(__END-__STRAT)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;}
 30 //***********************
 31 #define rint register int
 32 #define fo(a,b,c) for(rint a=b;a<=c;++a)
 33 #define fr(a,b,c) for(rint a=b;a>=c;--a)
 34 #define mem(a,b) memset(a,b,sizeof(a))
 35 #define pr printf
 36 #define sc scanf
 37 #define ls rt<<1
 38 #define rs rt<<1|1
 39 typedef pair<int,int> PII;
 40 typedef vector<int> VI;
 41 typedef long long ll;
 42 const double E=2.718281828;
 43 const double PI=acos(-1.0);
 44 const ll INF=(1LL<<60);
 45 const int inf=(1<<30);
 46 const double ESP=1e-9;
 47 const int mod=(int)1e9+7;
 48 const int N=(int)50010;
 49 
 50 int n,m,q;
 51 char a[N][12];
 52 int fa[24];
 53 void init()
 54 {
 55     for(int i=1;i<=20;++i)
 56         fa[i]=i;
 57 }
 58 int Find(int x)
 59 {
 60     return (x==fa[x])?x:(fa[x]=Find(fa[x]));
 61 }
 62 
 63 void combine(int a,int b)
 64 {
 65     int temp_a,temp_b;
 66 
 67     temp_a=Find(a);
 68     temp_b=Find(b);
 69 
 70     if(temp_a!=temp_b)
 71     {
 72         if(temp_a<temp_b)
 73             fa[temp_b]=temp_a;
 74         else
 75             fa[temp_a]=temp_b;
 76     }
 77 }
 78 
 79 struct Mat
 80 {
 81     ll a[12][12];
 82 }seg[N<<2],e,n1;
 83 Mat mul(Mat x,Mat y)
 84 {
 85     Mat c=Mat();
 86     for(int i=1;i<=10;++i)
 87     {
 88         for(int j=1;j<=10;++j)
 89         {
 90             for(int k=1;k<=10;++k)
 91                 c.a[i][j]+=(x.a[i][k]*y.a[k][j])%mod,c.a[i][j]%=mod;
 92         }
 93     }
 94     return c;
 95 }
 96 void up(int rt,int l,int r)
 97 {
 98     seg[rt]=mul(seg[ls],seg[rs]);
 99 }
100 
101 void Build(int l,int r,int rt)
102 {
103     if(l==r)
104     {
105         init();
106         for(int j=1;j<=m;++j)
107         {
108             if(j<m&&a[l][j]=='0'&&a[l][j+1]=='0')
109                 combine(j,j+1);
110         }
111         seg[rt]=Mat();
112         for(int j=1;j<=m;++j)
113             for(int k=1;k<=m;++k)
114                 if(a[l][j]=='0'&&a[l][k]=='0'&&Find(j)==Find(k))
115                     seg[rt].a[j][k]=1;
116         return;
117     }
118     int mid=(l+r)>>1;
119 
120     Build(l,mid,rt<<1);
121     Build(mid+1,r,rt<<1|1);
122     up(rt,l,r);
123 }
124 
125 void update_dot(int pos,Mat V,int l,int r,int rt)
126 {
127     if(l==r)
128     {
129         seg[rt]=V;
130         return;
131     }
132 
133     int mid=(l+r)>>1;
134     if(pos<=mid)
135         update_dot(pos,V,l,mid,rt<<1);
136     else
137         update_dot(pos,V,mid+1,r,rt<<1|1);
138     up(rt,l,r);
139 }
140 
141 int main()
142 {
143     e=n1=Mat();
144     for(int i=1;i<=10;++i)
145         e.a[i][i]=1,n1.a[1][i]=1;
146     sc("%d%d%d",&n,&m,&q);
147     for(int i=1;i<=n;++i)
148         sc("%s",a[i]+1);
149     Build(1,n,1);
150     for(int i=1;i<=q;++i)
151     {
152         int op,x,y;
153         sc("%d%d%d",&op,&x,&y);
154         if(op==1)
155         {
156             a[x][y]^=1;
157             init();
158             for(int j=1;j<=m;++j)
159             {
160                 if(j<m&&a[x][j]=='0'&&a[x][j+1]=='0')
161                     combine(j,j+1);
162             }
163             Mat temp=Mat();
164             for(int j=1;j<=m;++j)
165                 for(int k=1;k<=m;++k)
166                     if(a[x][j]=='0'&&a[x][k]=='0'&&Find(j)==Find(k))
167                         temp.a[j][k]=1;
168             update_dot(x,temp,1,n,1);
169         }
170         else
171             pr("%lld\n",seg[1].a[x][y]);
172     }
173     return 0;
174 }
175 
176 /**************************************************************************************/

猜你喜欢

转载自www.cnblogs.com/--HPY-7m/p/11874316.html
今日推荐