[tsA1490][2013中国国家集训队第二次作业]osu![概率dp+线段树+矩阵乘法]

时间:2023-03-09 14:33:08
[tsA1490][2013中国国家集训队第二次作业]osu![概率dp+线段树+矩阵乘法]

这样的题解只能舔题解了,,,qaq

清橙资料里有。。

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm> using namespace std; struct Matrix
{
double a,b,c,d;
}; struct node
{
double S0,S1;
Matrix S2;
}tree[]; double a[]; void push_up(const int num,const int pos)
{
node &temp1=tree[num<<],&temp2=tree[num<<|];
tree[num].S0=temp1.S0+temp2.S0-a[pos]*a[pos+];
tree[num].S1=temp1.S1+temp2.S1;
Matrix t1=temp1.S2,t2=temp2.S2;
tree[num].S2=(Matrix){t1.a*t2.a,t1.a*t2.b+t1.b,t1.c*t2.a+t2.c,t1.c*t2.b+t1.d+t2.d};
return ;
} void Change(const int l,const int r,const int num,const int s,const node d)
{
if(l==r)
{
a[l]=d.S0;
tree[num]=d;
return ;
} int mid=l+((r-l)>>); if(s<=mid)Change(l,mid,num<<,s,d);
else Change(mid+,r,num<<|,s,d); push_up(num,mid);
return ;
} node Calc(const node temp1,const node temp2,const int pos)
{
node A; A.S0=temp1.S0+temp2.S0-a[pos]*a[pos+];
A.S1=temp1.S1+temp2.S1; Matrix t1=temp1.S2,t2=temp2.S2;
A.S2=(Matrix){t1.a*t2.a,t1.a*t2.b+t1.b,t1.c*t2.a+t2.c,t1.c*t2.b+t1.d+t2.d}; return A;
} node Query(const int l,const int r,const int num,const int s,const int t)
{
if(s<=l && r<=t)
return tree[num]; int mid=l+((r-l)>>); if(t<=mid)return Query(l,mid,num<<,s,t);
if(s>mid) return Query(mid+,r,num<<|,s,t);
return Calc(Query(l,mid,num<<,s,t),Query(mid+,r,num<<|,s,t),mid);
} int main()
{
int n,m,i,op; scanf("%d%d",&n,&m); for(i=;i<=n;++i)
scanf("%lf",&a[i]);
for(i=;i<=n;++i)
Change(,n,,i,(node){a[i],a[i],(Matrix){a[i],a[i]*,a[i],a[i]}}); for(i=;i<=m;++i)
{
scanf("%d",&op); if(op==)
{
int x,y;
scanf("%d%d",&x,&y); node temp=Query(,n,,x,y);
printf("%.2f\n",temp.S0+temp.S1+temp.S2.d);
} if(op==)
{
int x;
double y; scanf("%d%lf",&x,&y);
Change(,n,,x,(node){y,y,(Matrix){y,y*,y,y}});
}
}
return ;
}