nowcoder wannafly 25 E:01串

时间:2021-11-15 18:06:00

E:01 串

链接

分析:

  线段树维护转移矩阵。每个节点是一个矩阵,区间内的矩阵乘起来就是答案矩阵。矩阵乘法满足结合律,所以线段树维护。

代码:

 #include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define Root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = ;
char s[N];
struct Node{
int a[][];
void Calc(int v) {
if (v) a[][] = , a[][] = , a[][] = , a[][] = ;
else a[][] = , a[][] = , a[][] = , a[][] = ;
}
}T[N << ];
Node operator + (const Node &A,const Node &B) {
Node C; memset(C.a, 0x3f, sizeof(C.a));
for (int k = ; k < ; ++k)
for (int i = ; i < ; ++i)
for (int j = ; j < ; ++j)
C.a[i][j] = min(C.a[i][j], A.a[i][k] + B.a[k][j]);
return C;
}
void build(int l,int r,int rt) {
if (l == r) { T[rt].Calc(s[l] - ''); return ; }
int mid = (l + r) >> ;
build(lson); build(rson);
T[rt] = T[rt << ] + T[rt << | ];
}
void update(int l,int r,int rt,int p,int v) {
if (l == r) { T[rt].Calc(v); return ; }
int mid = (l + r) >> ;
if (p <= mid) update(lson, p, v);
else update(rson, p, v);
T[rt] = T[rt << ] + T[rt << | ];
}
Node query(int l,int r,int rt,int L,int R) {
if (L <= l && r <= R) return T[rt];
int mid = (l + r) >> ;
if (R <= mid) return query(lson, L, R);
else if (L > mid) return query(rson, L, R);
else return query(lson, L, R) + query(rson, L, R);
}
int main() {
int n = read();
scanf("%s", s + );
build(Root);
Node ans;
for (int Q = read(); Q--; ) {
int opt = read(), x = read(), y = read();
if (opt == ) {
ans = query(Root, x, y);
printf("%d\n",min(ans.a[][], ans.a[][] + ));
}
else update(Root, x, y);
}
return ;
}