BZOJ 4597: [Shoi2016]随机序列

来源:互联网 发布:数据库质量控制 编辑:程序博客网 时间:2024/05/22 05:03

很可做的一道题

考虑一下一段序列的答案为b+x,x为最右连续一段是乘积,然后和为x,b则为对应的左边的和

然后考虑在右边加一个数k,分类讨论一下发现x'=kx,b'=2x+3b

于是就可以DP了

然后DP可以矩阵转移

于是就可以用线段树维护矩阵

就水过去了

(好像很简单哎,AC率好高的说)

#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<algorithm>#include<map>#include<set>#include<stack>#include<cstdlib>#include<ctime>#define rep(i,l,r) for(int i=l;i<=r;i++)#define per(i,r,l) for(int i=r;i>=l;i--)#define mmt(a,v) memset(a,v,sizeof(a))#define tra(i,u) for(int i=head[u];i;i=e[i].next)using namespace std;typedef long long ll;const int N=100000+5;const int P=(1e9)+7;struct matrix{ll a[2][2];void clr(){mmt(a,0);}matrix operator * (matrix &b){static matrix c;c.clr();rep(i,0,1)rep(j,0,1)rep(k,0,1)c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%P;return c;}};struct Node{int l,r;matrix t;}tr[N<<2];#define lc o<<1#define rc o<<1|1void pushup(int o){tr[o].t=tr[lc].t*tr[rc].t;}void update(int o,int p,int v){int l=tr[o].l,r=tr[o].r;if(l==r)tr[o].t.a[0][0]=v;else{int mid=l+r>>1;if(p<=mid)update(lc,p,v);else update(rc,p,v);pushup(o);}}int a[N];void build(int o,int l,int r){tr[o].l=l;tr[o].r=r;if(l==r){if(l==1)tr[o].t.a[0][0]=a[l];else{tr[o].t.a[0][0]=a[l];tr[o].t.a[0][1]=2;tr[o].t.a[1][0]=0;tr[o].t.a[1][1]=3;}}else{int mid=l+r>>1;build(lc,l,mid);build(rc,mid+1,r);pushup(o);}}int main(){//freopen("a.in","r",stdin);int n,q;scanf("%d%d",&n,&q);rep(i,1,n)scanf("%d",&a[i]);build(1,1,n);while(q--){int p,v;scanf("%d%d",&p,&v);update(1,p,v);printf("%lld\n",(tr[1].t.a[0][0]+tr[1].t.a[0][1])%P);}return 0;}


0 0
原创粉丝点击