1. 程式人生 > >codeforces 718C Sasha and Array

codeforces 718C Sasha and Array

線段樹維護矩陣資訊。。一定要把初值都賦好。。。

因為矩陣具有結合律,所以可以把子矩陣相加作為上一層的矩陣,對於更新的加值x,先線上段樹外將轉移矩陣自乘x次,

再新增到線段樹裡。主要是碼的準確。。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define mode 1000000007
using namespace std;
typedef unsigned long long ll;
void read(ll &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
struct node
{
	ll f[3][3];
}cs;
struct Tree
{
	node val,laz;
}tr[100005*4];
node operator*(node a,node b)
{
	node as;
	for(int i=1;i<=2;++i)
	{
		for(int j=1;j<=2;++j)
		{
			as.f[i][j]=0;
			for(int k=1;k<=2;++k)
			{
				as.f[i][j]+=a.f[i][k]*b.f[k][j]%mode;
				as.f[i][j]%=mode;
			}
		}
	}
	return as;
}
node ksm(node x,ll y)
{
	node www;
	www.f[1][1]=1;www.f[1][2]=0;
	www.f[2][1]=0;www.f[2][2]=1;
	while(y)
	{
		if(y%2==1)www=www*x;
		y=y/2;x=x*x;
	}
	return www;
}
node gett(ll x)
{
	if(x==2)
	{
		node yu;
		yu.f[1][1]=yu.f[2][1]=1;yu.f[1][2]=yu.f[2][2]=0;
		return yu;
	}
	if(x==1)
	{
		node yu;
		yu.f[1][1]=1;yu.f[2][1]=0;yu.f[1][2]=yu.f[2][2]=0;
		return yu;
	}
	node ww;
	ww.f[1][1]=1,ww.f[1][2]=0,ww.f[2][1]=1,ww.f[2][2]=0;
	return ksm(cs,x-2)*ww;
}
void pushup(int rt)
{
	tr[rt].val.f[1][1]=(tr[rt<<1].val.f[1][1]+tr[rt<<1|1].val.f[1][1])%mode;
	tr[rt].val.f[1][2]=(tr[rt<<1].val.f[1][2]+tr[rt<<1|1].val.f[1][2])%mode;
	tr[rt].val.f[2][1]=(tr[rt<<1].val.f[2][1]+tr[rt<<1|1].val.f[2][1])%mode;
	tr[rt].val.f[2][2]=(tr[rt<<1].val.f[2][2]+tr[rt<<1|1].val.f[2][2])%mode;
}
void biuld(int l,int r,int rt)
{
	tr[rt].laz.f[1][1]=1;tr[rt].laz.f[1][2]=0;
	tr[rt].laz.f[2][1]=0;tr[rt].laz.f[2][2]=1;
	if(l==r)
	{
		ll xx;
		read(xx);
		tr[rt].val=gett(xx);
		return;
	}
	int mid=(l+r)/2;
	biuld(l,mid,rt<<1);
	biuld(mid+1,r,rt<<1|1);
	pushup(rt);
}
void pushdown(int rt)
{
	//if(tr[rt].laz)
	tr[rt<<1].val=tr[rt].laz*tr[rt<<1].val;
	tr[rt<<1|1].val=tr[rt].laz*tr[rt<<1|1].val;
	tr[rt<<1].laz=tr[rt].laz*tr[rt<<1].laz;
	tr[rt<<1|1].laz=tr[rt].laz*tr[rt<<1|1].laz;
	tr[rt].laz.f[1][1]=1;tr[rt].laz.f[1][2]=0;
	tr[rt].laz.f[2][1]=0;tr[rt].laz.f[2][2]=1;
}
void insert(int L,int R,int rt,int l,int r,node v)
{
	if(L<=l&&r<=R)
	{
		tr[rt].val=v*tr[rt].val;
		tr[rt].laz=v*tr[rt].laz;
		return;
	}
	pushdown(rt);
	int mid=(l+r)/2;
	if(L<=mid)insert(L,R,rt<<1,l,mid,v);
	if(R>mid)insert(L,R,rt<<1|1,mid+1,r,v);
	pushup(rt);
}
ll query(int L,int R,int rt,int l,int r)
{
	if(L<=l&&r<=R)return tr[rt].val.f[1][1];
	pushdown(rt);
	int mid=(l+r)/2;
	if(R<=mid)return query(L,R,rt<<1,l,mid)%mode;
	else if(L>mid)return query(L,R,rt<<1|1,mid+1,r)%mode;
	else return (query(L,R,rt<<1,l,mid)+query(L,R,rt<<1|1,mid+1,r))%mode;
}
ll n,m,opt,l1,r1;ll po1;
int main()
{
	read(n);read(m);
	cs.f[1][1]=1,cs.f[1][2]=1,cs.f[2][1]=1;cs.f[2][2]=0;
	biuld(1,n,1);
	for(int i=1;i<=m;++i)
	{
		read(opt);
		if(opt==2)
		{
			read(l1);read(r1);
			printf("%I64d\n",query(l1,r1,1,1,n));
		}else
		{	
			read(l1);read(r1);read(po1);
			node wq=ksm(cs,po1);
			insert(l1,r1,1,1,n,wq);
		}
	}
	return 0;
}