# 【loli的胡策】测试4.16（线段树+概率期望dp）

(0w0在左侧，)在右侧
(0w在左侧，0)在右侧
(0在左侧，w0)在右侧
(在左侧，0w0)在右侧

## 代码

60pts

#include <cstdio>
#include <cstring>
#define LL long long
using namespace std;
const LL mod=4294967296LL;
const int N=50005;
int n,num[N],m,nxtz[N],nxtw[N];char st[N];
void add(int loc,int vv){for (int i=loc;i<=n;i+=i&(-i)) num[i]+=vv;}
int qurry(int loc)
{
int ans=0;
for (int i=loc;i>=1;i-=i&(-i)) ans+=num[i];
return ans;
}
int main()
{
freopen("0w0.in","r",stdin);
freopen("0w0.out","w",stdout);
scanf("%d%d",&n,&m);
scanf("%s",st+1);
while (m--)
{
char w[5],c[5];int x,y;
scanf("%s",w);scanf("%d",&x);
if (w[0]=='B')
{
scanf("%d",&y);scanf("%s",c);
for (int i=x;i<=y;i++) st[i]=c[0];
}else if (w[0]=='A')
{
scanf("%s",c);
st[x]=c[0];
}else
{
scanf("%d",&y);LL ans=0;
for (int i=1;i<=n;i++) num[i]=0;
int pointz=0,pointw=0;
for (int i=x;i<=y;i++)
{
if (st[i]==')')
for (int j=pointz;j;j=nxtz[j])
for (int k=pointw;k;k=nxtw[k])
if (k<j) break;
else ans=(ans+(LL)(qurry(k)-qurry(j))*(LL)(qurry(i)-qurry(k))%mod)%mod;
if (st[i]=='(') nxtz[i]=pointz,pointz=i;
if (st[i]=='w') nxtw[i]=pointw,pointw=i;
}
printf("%lld\n",ans);
}
}
}

100pts

#include <cstdio>
#include <cstring>
#include <iostream>
#define LL long long
using namespace std;
const LL mod=4294967296LL;
const int N=50005;
int n,m,f[N*4][6][6],ans,tmpans;char st[N],delta[N*4];
//( 0 w 0 )
//1 2 3 4 5
int pd(char v)
{
if (v=='(') return 1;
if (v=='0') return 2;
if (v=='w') return 3;
if (v==')') return 5;
return 0;
}
void updata(int now,int l,int r)
{
for (int i=1;i<=5;i++)
for (int j=i;j<=5;j++)
{
f[now][i][j]=f[l][i][j]+f[r][i][j];
for (int k=i;k<j;k++) f[now][i][j]+=f[l][i][k]*f[r][k+1][j];
}
}
void pushdown(int now,int l,int r,int mid)
{
if (delta[now])
{
memset(f[now<<1],0,sizeof(f[now<<1]));
memset(f[now<<1|1],0,sizeof(f[now<<1|1]));
int sb=pd(delta[now]);
if (sb==2)
{
f[now<<1][2][2]=f[now<<1][4][4]=mid-l+1;
f[now<<1|1][2][2]=f[now<<1|1][4][4]=r-mid;
}else
{
f[now<<1][sb][sb]=mid-l+1;
f[now<<1|1][sb][sb]=r-mid;
}
delta[now<<1]=delta[now];
delta[now<<1|1]=delta[now];
delta[now]=0;
}
}
void build(int now,int l,int r)
{
if (l==r)
{
tmpans=max(now,tmpans);
if (st[l]=='(') f[now][1][1]=1;
else if (st[l]=='0') f[now][2][2]=f[now][4][4]=1;
else if (st[l]=='w') f[now][3][3]=1;
else if (st[l]==')') f[now][5][5]=1;
return;
}
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
updata(now,now<<1,now<<1|1);
}
void qurry(int now,int l,int r,int lrange,int rrange)
{
if (lrange<=l && rrange>=r)
{
updata(ans,tmpans,now);
memcpy(f[tmpans],f[ans],sizeof(f[tmpans]));
return;
}
int mid=(l+r)>>1;pushdown(now,l,r,mid);
if (lrange<=mid) qurry(now<<1,l,mid,lrange,rrange);
if (rrange>mid) qurry(now<<1|1,mid+1,r,lrange,rrange);
updata(now,now<<1,now<<1|1);
}
void change(int now,int l,int r,int lrange,int rrange,char v)
{
if (lrange<=l && rrange>=r)
{
delta[now]=v;
memset(f[now],0,sizeof(f[now]));
int sb=pd(v);
if (sb==2) f[now][2][2]=f[now][4][4]=r-l+1;
else f[now][sb][sb]=r-l+1;
return;
}
int mid=(l+r)>>1;pushdown(now,l,r,mid);
if (lrange<=mid) change(now<<1,l,mid,lrange,rrange,v);
if (rrange>mid) change(now<<1|1,mid+1,r,lrange,rrange,v);
updata(now,now<<1,now<<1|1);
}
int main()
{
freopen("0w0.in","r",stdin);
freopen("0w0.out","w",stdout);
scanf("%d%d",&n,&m);
scanf("%s",st+1);
build(1,1,n);
ans=0;tmpans++;
while (m--)
{
char w[5],c[5];int x,y;
scanf("%s",w);scanf("%d",&x);
if (w[0]=='B')
{
scanf("%d",&y);scanf("%s",c);
change(1,1,n,x,y,c[0]);
}else if (w[0]=='A') scanf("%s",c),change(1,1,n,x,x,c[0]);
else
{
scanf("%d",&y);
memset(f[ans],0,sizeof(f[ans]));
memset(f[tmpans],0,sizeof(f[tmpans]));
qurry(1,1,n,x,y);
printf("%u\n",f[ans][1][5]);
}
}
}