A - Four Points 
题意: 
给出三个点,找到一个点,让这4个点组成一个矩形
 
思路: 
分别找到横纵坐标中只有一个的值。
 
时间复杂度: 
O ( 1 ) O(1) O ( 1 ) 
 
AC代码:  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 1e2 +5 ,M = 2e4 +10 ,INF = 0x3f3f3f3f ,mod = 1e9 +7 ;int  main ()  {    int  x,y,ans_x = 0 ,ans_y = 0 ;     for (int  i = 1  ; i <= 3  ; i++)     {         std::cin>>x>>y;         ans_x ^= x,ans_y ^= y;     }     std::cout<<ans_x<<' ' <<ans_y;     return  0 ; } 
 
 
  B - Get Closer 
题意: 
给出一个向量,将其变成单位向量。
 
思路: 
将向量除以他的模即可。
 
时间复杂度: 
O ( 1 ) O(1) O ( 1 ) 
 
AC代码: 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 1e2 +5 ,M = 2e4 +10 ,INF = 0x3f3f3f3f ,mod = 1e9 +7 ;int  main ()  {    double  x,y;     scanf ("%lf%lf" ,&x,&y);     printf ("%.10f %.10f" ,x / sqrt (x*x+y*y),y / sqrt (x*x+y*y));     return  0 ; } 
 
 
  C - Coupon 
题意: 
给定n个商品,每个商品的价格是a i a_i a i   ,现在有k张优惠券,每张优惠券可以减少某个商品x元(不得低于0),询问购买全部商品的最小花费。
 
思路: 
先保证不浪费优惠券的情况下,把尽可能多的商品价格减免到x元以下,然后如果还有优惠券剩余,我们对剩下的商品价格从高到低使用优惠券。
 
时间复杂度: 
O ( n l o g n ) O(nlogn) O ( n l o g n ) 
 
AC代码: 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 2e5 +10 ,M = 2e4 +10 ,INF = 0x3f3f3f3f ,mod = 1e9 +7 ;int  a[N];int  main ()  {    int  n,k,x;     std::cin>>n>>k>>x;     for (int  i = 1 ; i <= n ; i++)     {         std::cin>>a[i];         if (k == 0 )continue ;         if (k >= a[i]/x)         {             k -= a[i]/x;             a[i] %= x;         }         else          {             a[i] -= k * x;             k = 0 ;         }     }     ll sum = 0 ;     std::sort (a+1 ,a+1 +n,std::greater <int >());     for (int  i = 1  + k ; i <= n ; i++)sum += a[i];     std::cout<<sum;     return  0 ; } 
 
 
  D - 2-variable Function 
题意: 
给定一个数n,找到一个数x,满足下列两个条件:
x ≥ n x\geq n x ≥ n  
∃ a ∃ b , 使得 x = a 3 + a 2 b + a b 2 + b 3 ( a , b ∈ N ) \exists a\exists b,使得x=a^3+a^2b+ab^2+b^3(a,b\in N) ∃ a ∃ b , 使 得 x = a 3 + a 2 b + a b 2 + b 3 ( a , b ∈ N )  
 
 
 
思路: 
∵ n ≤ 1 0 18 \because n\leq 10^{18} ∵ n ≤ 1 0 1 8  
∴ a , b ≤ 1 0 6 \therefore a,b\leq10^{6} ∴ a , b ≤ 1 0 6  
我们可以使用双指针,从小到大枚举a a a  ,从大到小b b b  ,从而枚举出所有的x = a 3 + a 2 b + a b 2 + b 3 ≥ n x=a^3+a^2b+ab^2+b^3\geq n x = a 3 + a 2 b + a b 2 + b 3 ≥ n  ,并从中找到最小值。
 
时间复杂度: 
O ( n 3 ) O(\sqrt[3]{n}) O ( 3 n  ) 
 
AC代码:  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 1500 +10 ,M = 2e4 +10 ,INF = 0x3f3f3f3f ,mod = 1e9 +7 ;int  main ()  {    ll n;     std::cin>>n;     ll res = 1e18 ;     ll j = 1e6 ;     for (ll i = 0  ; i <= 1e6  ; i++)     {         ll temp = i*i*i+i*i*j+i*j*j+j*j*j;         while (temp >= n && j >= 0 )         {             res = std::min (res,temp);             j--;             temp = i*i*i+i*i*j+i*j*j+j*j*j;         }     }     std::cout<<res;     return  0 ; } 
 
 
  E - Bishop 2 
题意: 
给出一个n ∗ n n*n n ∗ n  的地图,其中′ . ′ '.' ′ . ′  是平地,其中#是障碍,并给出一个起点和终点,在不跨越障碍的情况下,可以往左上,右上,右下,左下四个斜角方向一次移动任意个单位,询问从起点移动到终点的最小步数,若不存在路径,则输出-1。
 
思路: 
修改正常BFS的拓展方式即可,每次拓展的时候把四个斜角方向可以拓展的点全部拓展。
 
时间复杂度: 
O ( n 2 ) O(n^2) O ( n 2 ) 
 
AC代码:  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 1500 +10 ,M = 2e4 +10 ,INF = 0x3f3f3f3f ,mod = 1e9 +7 ;struct  Node {    int  x,y,step; }que[N*N]; char  a[N][N];bool  book[N][N];int  ne[4 ][2 ] = {1 ,1 ,1 ,-1 ,-1 ,1 ,-1 ,-1 };int  n,start_x,start_y,end_x,end_y;bool  OK (int  x,int  y)  {    if (x<1 ||y<1 ||x>n||y>n||a[x][y]=='#' )return  false ;     return  true ; } void  bfs ()  {    int  head = 0 ,tail = -1 ;     que[++tail] = {start_x,start_y,0 };     book[start_x][start_y] = true ;     while (tail>=head)     {         auto  temp = que[head++];         if (temp.x == end_x && temp.y == end_y)         {             std::cout<<temp.step;             return ;         }         for (int  i = 0  ; i < 4  ; i++)         {             int  tx = temp.x + ne[i][0 ];             int  ty = temp.y + ne[i][1 ];             while (OK (tx,ty))             {                 if (!book[tx][ty])que[++tail] = {tx,ty,temp.step+1 };                 book[tx][ty] = true ;                 tx += ne[i][0 ];                 ty += ne[i][1 ];             }         }     }     std::cout<<-1 ; } int  main ()  {    std::cin>>n>>start_x>>start_y>>end_x>>end_y;     for (int  i = 1  ; i <= n ; i++)std::cin>>(a[i]+1 );     bfs ();     return  0 ; } 
 
 
  F - typewriter 
题意: 
给出n个键盘,每个键盘可以打印字母由一个字符串表示,现在要打印一个长度为L的字符串,每次选择一个键盘打印字符串,可以打印出多少不同的字符串。
 
思路: 
应用容斥原理,以n=3为例:
ans = 
+(只使用第一个键盘)+(只使用第二个键盘)+(只使用第三个键盘)-(只使用第一个键盘和第二个键盘共有的字母打印)-(只使用第一个键盘和第三个键盘共有的字母打印)-(只使用第二个键盘和第三个键盘共有的字母打印)+(使用所用键盘共有的字母打印)。
 
因此我们只需要枚举上述所有情况,求出答案即可。
 
时间复杂度: 
N个字母所能打印的长度为L的字符串的个数为N L N^{L} N L  。 
使用快速幂会花费O ( l o g L ) O(logL) O ( l o g L )  的时间。 
此外,枚举所有的情况是O ( 2 n ) O(2^n) O ( 2 n )  
所以总时间复杂度为O ( 2 n l o g L ) O(2^nlogL) O ( 2 n l o g L ) 
 
AC代码:  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 30 ,M = 2e4 +10 ,INF = 0x3f3f3f3f ,mod = 998244353 ;bool  temp[N],a[N][N];ll ans,n,len; ll quickPow (ll x,ll k)   {    ll res = 1 ;     while (k)     {         if (k&1 )res = (x * res) % mod;         x = x * x % mod;         k >>= 1 ;     }     return  res; } void  dfs (int  u,int  cnt)  {    if (u==n)     {         if (cnt==0 )return ;         int  count = 0 ;         for (int  i = 0  ; i < 26  ; i++)if (temp[i])count++;         if (cnt&1 )ans = (ans + quickPow (count,len)) % mod;         else  ans = (ans - quickPow (count,len) + mod) % mod;         return ;     }     dfs (u+1 ,cnt);     bool  last[N];     memcpy (last,temp,sizeof  temp);     for (int  i = 0  ; i < 26  ; i++)temp[i] &= a[u][i];     dfs (u+1 ,cnt+1 );     memcpy (temp,last,sizeof  temp); } int  main ()  {    std::ios::sync_with_stdio (false );     std::cin.tie (nullptr );     std::cout.tie (nullptr );     std::cin>>n>>len;     for (int  i = 0  ; i < n ; i++)     {         std::string s;         std::cin>>s;         for (int  j = 0  ; j < s.size () ; j++) a[i][s[j]-'a' ] = true ;     }     for (int  i = 0  ; i < 26  ; i++)temp[i] = true ;     dfs (0 ,0 );     std::cout<<ans;     return  0 ; } 
 
 
  G - Game on Tree 3 
题意: 
给定一棵根为1的树,除了根,每个点都有一个权值w i w_i w i   ,现在小明和小红从根节点开始按照如下规则玩一个游戏:
小红任意选择一个点,把这个点的权值变为0 
小明从当前点出发,可以走到任意一个儿子节点 
然后小明可以决定是否结束游戏(如果小明在叶子节点则必须结束游戏) 
 
 
最后小明获得的分数就是小明所在点的权值,小明希望获得的分数尽可能得高,小红希望小明获得的分数尽可能的低,假设两人都足够聪明的情况下(即总是做出对当前最有利的操作),小明可以获得的最大分数是多少。
 
思路: 
使用动态规划(树形dp)和二分答案。 
考虑对于某一个分数x x x  ,小明是否存在方案可以获得比x x x  大的分数:
我们令w u ≥ x w_u\geq x w u  ≥ x  的点v u v_u v u   为1,w u < x w_u< x w u  < x  的点v u v_u v u   为0,。 
如果要使小明无法获得分数x x x  ,那么必须要使这些为1的点变成0,我们假设d p [ i ] dp[i] d p [ i ]  为小明在点i i i  开始游戏小红所需要的消除次数。 
那么对于某个点的d p [ i ] dp[i] d p [ i ]  ,我们可以用如下式子求出:
d p [ i ] = v i + m a x ( 0 , ∑ c d p [ c ] − 1 ) ( c ∈ c h i l d r e n i ) dp[i]=v_i+max(0,\sum_{c}dp[c]-1)(c\in children_i) d p [ i ] = v i  + m a x ( 0 , ∑ c  d p [ c ] − 1 ) ( c ∈ c h i l d r e n i  ) 
 
 
如果当前点v i = 1 v_i=1 v i  = 1  ,那么肯定是要消除的,在小明走到儿子节点之前,我们还有一次消除机会(开始游戏时小红是先手),所以还要加上( m a x ( ∑ c d p [ c ] − 1 , 0 ) ) (max(\sum_{c}dp[c]-1,0)) ( m a x ( ∑ c  d p [ c ] − 1 , 0 ) )  。
 
最后可以求得d p [ 0 ] dp[0] d p [ 0 ]  ,如果d p [ 0 ] ! = 0 dp[0]!=0 d p [ 0 ] ! = 0  ,那么小明是可以获得一个比x x x  大的分数的。
 
最后用二分找到最大值即可。
 
时间复杂度: 
O ( n l o g ( m a x A i ) ) O(nlog(maxA_i)) O ( n l o g ( m a x A i  ) ) 
 
AC代码:  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 2e5 +10 ,M = N * 2 ,INF = 0x3f3f3f3f ,mod = 998244353 ;int  h[N],e[M],ne[M],idx;int  w[N],dp[N];void  add (int  a,int  b)  {    e[idx] = b,ne[idx] = h[a],h[a] = idx++; } void  dfs (int  u,int  fa,int  val)  {    dp[u] = (w[u] >= val);     int  sum = 0 ;     for (int  i = h[u] ; ~i ; i = ne[i])     {         int  v = e[i];         if (v==fa)continue ;         dfs (v,u,val);         sum += dp[v];     }     dp[u] += std::max (0 ,sum-1 ); } bool  check (int  val)  {    dfs (1 ,-1 ,val);     return  dp[1 ] != 0 ; } int  main ()  {    std::ios::sync_with_stdio (false );     std::cin.tie (nullptr );     std::cout.tie (nullptr );     int  n;     std::cin>>n;     memset (h,-1 ,sizeof  h);     int  max = -1 ;     for (int  i = 2  ; i <= n ; i++)std::cin>>w[i],max = std::max (max,w[i]);     for (int  i = 1  ; i < n ; i++)     {         int  a,b;         std::cin>>a>>b;         add (a,b),add (b,a);     }     w[0 ] = -1 ;     int  L = 0 ,R = max;     while (R>L)     {         int  mid = L + R + 1  >> 1 ;         if (check (mid))L = mid;         else  R = mid - 1 ;     }     std::cout<<L;     return  0 ; } 
 
 
  Ex - 01? Queries 
题意: 
给定一个由’0’,‘1’和’?'组成的字符串,我们可以任意得将′ ? ′ '?' ′ ? ′  替换成′ 0 ′ '0' ′ 0 ′  或′ 1 ′ '1' ′ 1 ′  ,求字符串的所有子串可以形成的不同的01串有多少种。 
现在存在q个操作,每次操作将第x个字符变成′ 0 ′ , ′ 1 ′ 或 ′ ? ′ '0','1'或'?' ′ 0 ′ , ′ 1 ′ 或 ′ ? ′  ,询问每次操作后的答案。
 
思路: 
我们先考虑在某种情况下的01串种数。 
考虑动态规划,定义d p [ i ] [ 0 ] 和 d p [ i ] [ 1 ] dp[i][0]和dp[i][1] d p [ i ] [ 0 ] 和 d p [ i ] [ 1 ]  分别表示前i i i  个字母所能组成的以0结尾的和以1结尾的种数。 
那么应该有如下状态转移方程:
s [ i ] = 0 s[i]=0 s [ i ] = 0  
d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] + d p [ i − 1 ] [ 1 ] + 1 dp[i][0]=dp[i-1][0]+dp[i-1][1]+1 d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] + d p [ i − 1 ] [ 1 ] + 1  
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] dp[i][1]=dp[i-1][1] d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ]  
s [ i ] = 1 s[i]=1 s [ i ] = 1  
d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] dp[i][0]=dp[i-1][0] d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ]  
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] + d p [ i − 1 ] [ 0 ] + 1 dp[i][1]=dp[i-1][1]+dp[i-1][0]+1 d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] + d p [ i − 1 ] [ 0 ] + 1  
s [ i ] =   ? s[i]= \ ? s [ i ] =   ?  
d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] + d p [ i − 1 ] [ 1 ] + 1 dp[i][0]=dp[i-1][0]+dp[i-1][1]+1 d p [ i ] [ 0 ] = d p [ i − 1 ] [ 0 ] + d p [ i − 1 ] [ 1 ] + 1  
d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] + d p [ i − 1 ] [ 0 ] + 1 dp[i][1]=dp[i-1][1]+dp[i-1][0]+1 d p [ i ] [ 1 ] = d p [ i − 1 ] [ 1 ] + d p [ i − 1 ] [ 0 ] + 1  
 
 
我们将上述状态转移方程用矩阵表示:
[ d p [ i ] [ 0 ] d p [ i ] [ 1 ] 1 ] = A s i [ d p [ i − 1 ] [ 0 ] d p [ i − 1 ] [ 1 ] 1 ] \begin{bmatrix} dp[i][0] \\dp[i][1] \\1  \end{bmatrix}=A_{s_{i}}\begin{bmatrix} dp[i-1][0]\\ dp[i-1][1]\\1 \end{bmatrix} ⎣ ⎢ ⎡  d p [ i ] [ 0 ] d p [ i ] [ 1 ] 1  ⎦ ⎥ ⎤  = A s i   ⎣ ⎢ ⎡  d p [ i − 1 ] [ 0 ] d p [ i − 1 ] [ 1 ] 1  ⎦ ⎥ ⎤   
分别的,对于不同的A s i A_{s_{i}} A s i    ,有:
s [ i ] = 0 : s[i]=0: s [ i ] = 0 :  
A s i = [ 1 1 1 0 1 0 0 0 1 ] A_{s_{i}}=\begin{bmatrix}
1& 1 &1 \\ 
0&1  & 0\\ 
0& 0 & 1
\end{bmatrix} A s i   = ⎣ ⎢ ⎡  1 0 0  1 1 0  1 0 1  ⎦ ⎥ ⎤   
s [ i ] = 1 : s[i]=1: s [ i ] = 1 :  
A s i = [ 1 0 0 1 1 1 0 0 1 ] A_{s_{i}}=\begin{bmatrix}
1& 0 &0 \\ 
1&1  & 1\\ 
0& 0 & 1
\end{bmatrix} A s i   = ⎣ ⎢ ⎡  1 1 0  0 1 0  0 1 1  ⎦ ⎥ ⎤   
s [ i ] =   ? : s[i]=\ ?: s [ i ] =   ? :  
A s i = [ 1 1 1 1 1 1 0 0 1 ] A_{s_{i}}=\begin{bmatrix}
1& 1 &1 \\ 
1&1  & 1\\ 
0& 0 & 1
\end{bmatrix} A s i   = ⎣ ⎢ ⎡  1 1 0  1 1 0  1 1 1  ⎦ ⎥ ⎤  
 
 
此外有[ d p [ i ] [ 0 ] d p [ i ] [ 1 ] 1 ] = A s i A s i − 1 … A s 1 [ d p [ 0 ] [ 0 ] d p [ 0 ] [ 1 ] 1 ] = A s i A s i − 1 … A s 1 [ 0 0 1 ] \begin{bmatrix} dp[i][0] \\dp[i][1] \\1  \end{bmatrix}=A_{s_{i}}A_{s_{i-1}}\dots A_{s_{1}}\begin{bmatrix} dp[0][0]\\ dp[0][1]\\1 \end{bmatrix}=A_{s_{i}}A_{s_{i-1}}\dots A_{s_{1}}\begin{bmatrix} 0\\ 0\\1 \end{bmatrix} ⎣ ⎢ ⎡  d p [ i ] [ 0 ] d p [ i ] [ 1 ] 1  ⎦ ⎥ ⎤  = A s i   A s i − 1   … A s 1   ⎣ ⎢ ⎡  d p [ 0 ] [ 0 ] d p [ 0 ] [ 1 ] 1  ⎦ ⎥ ⎤  = A s i   A s i − 1   … A s 1   ⎣ ⎢ ⎡  0 0 1  ⎦ ⎥ ⎤  
 
我们可以用线段树维护每一个矩阵,这样修改操作可以在l o g n logn l o g n  时间内完成。
 
时间复杂度: 
O ( q l o g n ) O(qlogn) O ( q l o g n ) 
 
AC代码:  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 #include <bits/stdc++.h>  typedef  long  long  ll;const  int  N = 1e5 +10 ,M = N * 2 ,INF = 0x3f3f3f3f ,mod = 998244353 ;struct  Node {    int  l,r;     ll a[3 ][3 ]; }tr[N*4 ]; char  s[N];int  n,q;void  pushup (int  u)  {    memset (tr[u].a,0 ,sizeof  tr[u].a);     for (int  i = 0  ; i < 3  ; i++)         for (int  j = 0  ; j < 3  ; j++)         {             for (int  k = 0  ; k < 3  ; k++)                 tr[u].a[i][j] = (tr[u].a[i][j] + tr[u<<1 ].a[i][k]*tr[u<<1 |1 ].a[k][j])%mod;         } } void  assign (Node &root,char  ch)  {    if (ch=='0' )     {         root.a[0 ][0 ] = 1 ;         root.a[0 ][1 ] = 1 ;         root.a[0 ][2 ] = 1 ;         root.a[1 ][0 ] = 0 ;         root.a[1 ][1 ] = 1 ;         root.a[1 ][2 ] = 0 ;         root.a[2 ][0 ] = 0 ;         root.a[2 ][1 ] = 0 ;         root.a[2 ][2 ] = 1 ;     }     else  if (ch=='1' )     {         root.a[0 ][0 ] = 1 ;         root.a[0 ][1 ] = 0 ;         root.a[0 ][2 ] = 0 ;         root.a[1 ][0 ] = 1 ;         root.a[1 ][1 ] = 1 ;         root.a[1 ][2 ] = 1 ;         root.a[2 ][0 ] = 0 ;         root.a[2 ][1 ] = 0 ;         root.a[2 ][2 ] = 1 ;     }     else      {         root.a[0 ][0 ] = 1 ;         root.a[0 ][1 ] = 1 ;         root.a[0 ][2 ] = 1 ;         root.a[1 ][0 ] = 1 ;         root.a[1 ][1 ] = 1 ;         root.a[1 ][2 ] = 1 ;         root.a[2 ][0 ] = 0 ;         root.a[2 ][1 ] = 0 ;         root.a[2 ][2 ] = 1 ;     } } void  build (int  u,int  l,int  r)  {    if (l==r)     {         tr[u] = {l,r};         assign (tr[u],s[r]);     }     else      {         int  mid = l + r >> 1 ;         tr[u] = {l,r};         build (u<<1 ,l,mid),build (u<<1 |1 ,mid+1 ,r);         pushup (u);     } } void  modify (int  u,int  x,char  ch)  {    if (tr[u].l==x&&tr[u].r==x)     {         assign (tr[u],ch);     }     else      {         int  mid = tr[u].l + tr[u].r >> 1 ;         if (x <= mid)modify (u<<1 ,x,ch);         else  modify (u<<1 |1 ,x,ch);         pushup (u);     } } int  main ()  {    std::ios::sync_with_stdio (false );     std::cin.tie (nullptr );     std::cout.tie (nullptr );     std::cin>>n>>q;     std::cin>>(s+1 );     build (1 ,1 ,n);     while (q--)     {         int  x;         char  ch;         std::cin>>x>>ch;         modify (1 ,x,ch);         std::cout<<(tr[1 ].a[0 ][2 ]+tr[1 ].a[1 ][2 ])%mod<<'\n' ;     }     return  0 ; }