202012CSPT5星际旅行

题意:
n ( n < = 1000000000 ) n(n<=1000000000) n(n<=1000000000)个点,每个点有三维坐标 x , y , z x,y,z x,y,z且每个点坐标为0。有 m ( m < = 40000 ) m(m<=40000) m(m<=40000)个操作:
1 1 1:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别增加 a , b , c a,b,c a,b,c
2 2 2:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别乘 k k k
3 3 3:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别变换为 < y , z , x > <y,z,x>
4 4 4:对 [ L , R ] [L,R] [L,R]内所有点的三维坐标分别相加之后求平方之和,再mod1,000,000,007;

#define ll long long 
#define maxn 500000
struct Node
{
	ll sumx,sumy,sumz;//x,y,z三维的答案 
	ll addx,addy,addz;//x,y,z的加法懒标记
	ll mul,ro;//乘法懒标记和旋转懒标记 
	ll l,r;
	ll len;//离散化需要来记录真正的区间长度 
}t[maxn<<3];
ll q[maxn][6];//离散化存储 
vector<int> v;
ll mod=1000000007;
int n,m;
void build(ll p,ll l,ll r)
{
	t[p].l=l;t[p].r=r;t[p].mul=1;
	if(l==r)
	{
		if(l==v.size()-1)t[p].len=0;
		else t[p].len=v[l+1]-v[l];
		t[p].sumx=t[p].sumy=t[p].sumz=0;return ;
	}
	ll mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	t[p].sumx=(t[p*2].sumx+t[p*2+1].sumx)%mod;
	t[p].sumy=(t[p*2].sumy+t[p*2+1].sumy)%mod;
	t[p].sumz=(t[p*2].sumz+t[p*2+1].sumz)%mod;
	t[p].len=t[p*2].len+t[p*2+1].len;
}
void spread(ll p)
{
	if(t[p].l==t[p].r)
	{	
		t[p].mul=1;
    	t[p].ro=0;
    	t[p].addx=t[p].addy=t[p].addz=0;
    	return ;
	}
	t[p*2].sumx=(((t[p].mul%mod)*t[p*2].sumx)%mod+((t[p*2].len)*(t[p].addx%mod))%mod)%mod;
	t[p*2].sumy=(((t[p].mul%mod)*t[p*2].sumy)%mod+((t[p*2].len)*(t[p].addy%mod))%mod)%mod;
	t[p*2].sumz=(((t[p].mul%mod)*t[p*2].sumz)%mod+((t[p*2].len)*(t[p].addz%mod))%mod)%mod;
	t[p*2+1].sumx=(((t[p].mul%mod)*t[p*2+1].sumx)%mod+((t[p*2+1].len)*(t[p].addx%mod))%mod)%mod;
	t[p*2+1].sumy=(((t[p].mul%mod)*t[p*2+1].sumy)%mod+((t[p*2+1].len)*(t[p].addy%mod))%mod)%mod;
	t[p*2+1].sumz=(((t[p].mul%mod)*t[p*2+1].sumz)%mod+((t[p*2+1].len)*(t[p].addz%mod))%mod)%mod;
	
	for(ll i=0;i<t[p].ro;i++)//lazy将儿子旋转 
	{
		swap(t[p*2].sumx,t[p*2].sumy);
		swap(t[p*2].sumy,t[p*2].sumz);
		swap(t[p*2+1].sumx,t[p*2+1].sumy);
		swap(t[p*2+1].sumy,t[p*2+1].sumz);
	}
	
	ll u,v,w;
	u=t[p].addx;v=t[p].addy;w=t[p].addz;
	for(ll i=0;i<t[p*2].ro;i++){swap(v,w);swap(u,v);}
	t[p*2].addx=((t[p*2].addx%mod)*(t[p].mul%mod)%mod+u%mod)%mod;
	t[p*2].addy=((t[p*2].addy%mod)*(t[p].mul%mod)%mod+v%mod)%mod;
	t[p*2].addz=((t[p*2].addz%mod)*(t[p].mul%mod)%mod+w%mod)%mod;
	
	u=t[p].addx;v=t[p].addy;w=t[p].addz;
	for(ll i=0;i<t[p*2+1].ro;i++){swap(v,w);swap(u,v);}
	t[p*2+1].addx=((t[p*2+1].addx%mod)*(t[p].mul%mod)%mod+u%mod)%mod;
	t[p*2+1].addy=((t[p*2+1].addy%mod)*(t[p].mul%mod)%mod+v%mod)%mod;
	t[p*2+1].addz=((t[p*2+1].addz%mod)*(t[p].mul%mod)%mod+w%mod)%mod;
	
	t[p*2].mul=((t[p*2].mul%mod)*t[p].mul)%mod;
    t[p*2+1].mul=((t[p*2+1].mul%mod)*t[p].mul)%mod;
    t[p*2].ro=(t[p*2].ro+t[p].ro)%3; 
    t[p*2+1].ro=(t[p*2+1].ro+t[p].ro)%3; 
    t[p].addx=t[p].addy=t[p].addz=0;
	t[p].mul=1;t[p].ro=0;
}
void rot(ll p,ll l,ll r)
{
	if(t[p].r<l||t[p].l>r)return ;
	if(t[p].l>=l&&t[p].r<=r)
	{
		swap(t[p].sumx,t[p].sumy);
		swap(t[p].sumy,t[p].sumz);
		t[p].ro=(t[p].ro+1)%3;
		return ;
	}
	if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
	spread(p);
	t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
	t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
	t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
	
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)rot(p*2,l,r);
	if(mid<r)rot(p*2+1,l,r);
	t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
	t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
	t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
} 
void add(ll p,ll l,ll r,ll a,ll b,ll c)
{
	if(t[p].r<l||t[p].l>r)return ;
	if(t[p].l>=l&&t[p].r<=r)//加法区间覆盖当前子树 
	{
		t[p].sumx=(t[p].sumx%mod+a*(t[p].len)%mod)%mod;
		t[p].sumy=(t[p].sumy%mod+b*(t[p].len)%mod)%mod;
		t[p].sumz=(t[p].sumz%mod+c*(t[p].len)%mod)%mod;
		for(ll i=0;i<t[p].ro;i++){swap(b,c);swap(a,b);}//有标记将其右移,因为sum已经左移了,这样正好对上 
		t[p].addx=(t[p].addx%mod+a%mod)%mod;
		t[p].addy=(t[p].addy%mod+b%mod)%mod;
		t[p].addz=(t[p].addz%mod+c%mod)%mod;
		return ;
	}
	if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
	spread(p);
	t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
	t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
	t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)add(p*2,l,r,a,b,c);
	if(mid<r)add(p*2+1,l,r,a,b,c);
	t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
	t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
	t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
}
void Mul(ll p,ll l,ll r,ll k)
{
	if(t[p].r<l||t[p].l>r)return ;
	if(t[p].l>=l&&t[p].r<=r)
	{
		t[p].addx=((t[p].addx%mod)*(k%mod))%mod;
		t[p].addy=((t[p].addy%mod)*(k%mod))%mod;
		t[p].addz=((t[p].addz%mod)*(k%mod))%mod;
		t[p].mul=((t[p].mul%mod)*(k%mod))%mod;
		t[p].sumx=((t[p].sumx%mod)*(k%mod))%mod;
		t[p].sumy=((t[p].sumy%mod)*(k%mod))%mod;
		t[p].sumz=((t[p].sumz%mod)*(k%mod))%mod;
		return ;
	}
	if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
	spread(p);
   	t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
	t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
	t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)Mul(p*2,l,r,k);
	if(mid<r)Mul(p*2+1,l,r,k);
	t[p].sumx=(t[p*2].sumx%mod+t[p*2+1].sumx%mod)%mod;
	t[p].sumy=(t[p*2].sumy%mod+t[p*2+1].sumy%mod)%mod;
	t[p].sumz=(t[p*2].sumz%mod+t[p*2+1].sumz%mod)%mod;
}
void ask(ll p,ll l,ll r,ll &a,ll &b,ll &c)
{
	if(t[p].r<l||t[p].l>r)return ;
	if(t[p].l>=l&&t[p].r<=r)
	{
		a=(t[p].sumx%mod+a)%mod;
		b=(t[p].sumy%mod+b)%mod;
		c=(t[p].sumz%mod+c)%mod;
		return ;
	}
	if(t[p].addx||t[p].addy||t[p].addz||t[p].mul||t[p].ro)
	spread(p);
	ll mid=(t[p].l+t[p].r)>>1;
	if(l<=mid)ask(p*2,l,r,a,b,c);
	if(mid<r)ask(p*2+1,l,r,a,b,c);
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>q[i][0]>>q[i][1]>>q[i][2];//op,l,r
		q[i][2]++;
		v.push_back(q[i][1]);v.push_back(q[i][2]);
		if(q[i][0]==1)//add
		for(int j=3;j<=5;j++)cin>>q[i][j];
		else if(q[i][0]==2)cin>>q[i][3];//mul
	}
	v.push_back(-999);
	sort(v.begin(),v.end());//排序保证序列是有序的
	v.erase(unique(v.begin(),v.end()),v.end());//将多余的数字去除
	for(int i=1;i<=m;i++)
	{//二分离散化 
		q[i][1]=lower_bound(v.begin(),v.end(),q[i][1])-v.begin();
        q[i][2]=lower_bound(v.begin(),v.end(),q[i][2])-v.begin();
	}
	ll ans=v.size()-1;
	build(1,1,ans);
	for(int i=1;i<=m;i++)
	{
		if(q[i][0]==1)
		{
			add(1,q[i][1],q[i][2]-1,q[i][3],q[i][4],q[i][5]);
		}
		if(q[i][0]==2)
		{
			Mul(1,q[i][1],q[i][2]-1,q[i][3]);
		}
		if(q[i][0]==3)
		{
			rot(1,q[i][1],q[i][2]-1);
		}
		if(q[i][0]==4)
		{
			ll ansx=0,ansy=0,ansz=0;
			ask(1,q[i][1],q[i][2]-1,ansx,ansy,ansz);
			cout<<((ansx%mod)*(ansx%mod)%mod+(ansy%mod)*(ansy%mod)%mod+(ansz%mod)*(ansz%mod))%mod<<endl;
		}
	}
	return 0;
}

你可能感兴趣的:(CSP,算法)