今天状态不错把这题A了,那天打BC的时候看错题了= =
题意:有n层楼,每层楼有两个门,每个门都通过两个楼梯和下一层的两个门相连,m次操作,把某条楼梯的状态改变(可用与不可用),或者询问从一层到另一层有多少种走法,需要注意的就是如果你从x-1层走到了x层的a门,那么你只能从a门再走到下一层。当时就死在这了。。
一个线段树t[x][md],md表示四种从l层走到r层的进与出的四种搭配(0-0,0-1,1-0,1-1),建树、更新的时候都是分别更新这四个值,查询的时候返回一个结构,里面存的是这四个值x1,x2,x3,x4,如果L和R在左右子树都有一部分的话就用返回的两个结构相乘得到答案。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
using namespace std;
#define mod 1000000007
#define lson l,m,x<<1
#define rson m,r,x<<1|1
#define LL __int64
int n;
LL t[200005][4];
int dir[4][2]={0,0,0,1,1,0,1,1};
typedef struct aa
{
LL x1,x2,x3,x4;
aa(){};
aa(LL a,LL b,LL c,LL d)
{
x1=a;x2=b;x3=c;x4=d;
}
} Ans;
void es_tree(int l,int r,int x)
{
if(r==l+1)
{
t[x][0]=t[x][1]=t[x][2]=t[x][3]=1;
return;
}
int m=(l+r)/2;
es_tree(lson);
es_tree(rson);
t[x][0]=t[x<<1][0]*t[x<<1|1][0]+t[x<<1][1]*t[x<<1|1][2];
t[x][1]=t[x<<1][0]*t[x<<1|1][1]+t[x<<1][1]*t[x<<1|1][3];
t[x][2]=t[x<<1][2]*t[x<<1|1][0]+t[x<<1][3]*t[x<<1|1][2];
t[x][3]=t[x<<1][2]*t[x<<1|1][1]+t[x<<1][3]*t[x<<1|1][3];
t[x][0]%=mod;
t[x][1]%=mod;
t[x][2]%=mod;
t[x][3]%=mod;
}
void update(int L,int mode,int l,int r,int x)
{
if(l==L&&r==L+1)
{
t[x][mode]^=1;
return;
}
int m=(l+r)/2;
if(L=m) return query(L,R,rson);
Ans a=query(L,m,lson),b=query(m,R,rson);
return Ans((a.x1*b.x1+a.x2*b.x3)%mod,(a.x1*b.x2+a.x2*b.x4)%mod,(a.x3*b.x1+a.x4*b.x3)%mod,(a.x3*b.x2+a.x4*b.x4)%mod);
}
int select(int from,int to)
{
for(int i=0;i<=3;i++)
if(from==dir[i][0]&&to==dir[i][1]) return i;
}
int main()
{
int md,x,f,to,a,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(t,0,sizeof(t));
es_tree(1,n,1);
while(m--)
{
scanf("%d",&md);
if(md)
{
scanf("%d%d%d",&x,&f,&to);
int a=select(f-1,to-1);
update(x,a,1,n,1);
}
else
{
scanf("%d%d",&f,&to);
Ans ret=query(f,to,1,n,1);
printf("%I64d\n",(ret.x1+ret.x2+ret.x3+ret.x4)%mod);
}
}
}
return 0;
}