您的位置:首页 > 其它

3494. 【NOIP2013模拟联考13】线段(segment) (2017.9B组)

2017-10-07 22:32 423 查看
Description

数轴上有很多单位线段,一开始时所有单位线段的权值都是1。有两种操作,第一种操作将某一区间内的单位线段权值乘以w,第二种操作将某一区间内的单位线段权值取w次幂。并且你还需要回答一些询问,每个询问需要求出某一区间的单位线段权值之积。由于答案可能很大,你只需要求出答案 mod (10^9+7)的值。

说明:n个点只有n-1条线段。

Input

第一行一个整数n,表示操作数量。

接下来n行,每行第一个整数表示操作类型,0表示第一种操作,1表示第二种操作,2表示询问,如果第一个数是0或1,则接下来3个数,表示操作区间和w,否则接下来两个数,表示询问区间。

Output

对于每组询问,输出一行,表示所求答案。

Sample Input

7

0 0 2 3

1 1 3 2

2 1 3

0 0 3 2

1 1 3 2

2 1 3

2 0 3

Sample Output

9

1296

7776

想法:

第一次接触动态开点线段树

其实比较简单啦

只不过是如果有需要的话给某个节点赋予它儿子而已

这道题

下传两个lazy标记

先^a,再乘b

下传标记^a*b,至^c *d

c=c*a

d=d^a*b

细节较多

code

线段树最好把多个操作分类,合在一起打会好调很多

#include <cstdio>
#include <cstring>
#include <iostream>
#define ll long long
using namespace std;
const ll maxn=1e9+7,maxN=2e6,max1=1e9+7;
struct zhj
{
ll l,r,ans,mi,cheng;
};
ll q,i,x1,tot,ans,zl,y1,z1;
zhj tree[maxN];
ll ksm(ll x,ll y)
{
ll k=1,z=x%maxn;
y%=maxn-1;
while (y>0)
{
if (y&1==1) k=(k*z)%maxn;
y>>=1;
z=(z*z)%maxn;
}
return k;
}
void xg(ll x,ll l,ll r,ll a,ll b)
{
tree[x].ans=(ksm(tree[x].ans,a)*ksm(b,r-l+1))%maxn;
tree[x].mi=(tree[x].mi*a)%(maxn-1);
tree[x].cheng=(ksm(tree[x].cheng,a)*b)%maxn;
return;
}
void change(ll x,ll head,ll tail,ll l,ll r,ll zl,ll y)
{
if ((head==l)&&(tail==r))
{
if (zl==1)
{
tree[x].ans=(tree[x].ans*ksm(y,tail-head+1))%maxn;
tree[x].cheng=(tree[x].cheng*y)%maxn;
}
if (zl==2)
{
tree[x].ans=ksm(tree[x].ans,y);
tree[x].mi=(tree[x].mi*y)%(maxn-1);
tree[x].cheng=ksm(tree[x].cheng,y)%maxn;
}
if (zl==3)
{
ans=(ans*tree[x].ans)%maxn;
}
return;
}
ll mid=(head+tail)/2,l1,r1;
if (tree[x].l>0) l1=tree[x].l;
else tot++,tree[x].l=tot,l1=tot,tree[l1].ans=1,tree[l1].cheng=1,tree[l1].mi=1;

if (tree[x].r>0) r1=tree[x].r;
else tot++,tree[x].r=tot,r1=tot,tree[r1].ans=1,tree[r1].cheng=1,tree[r1].mi=1;;

tree[x].mi%=maxn-1;
xg(l1,head,mid,tree[x].mi,tree[x].cheng);
xg(r1,mid+1,tail,tree[x].mi
4000
,tree[x].cheng);
tree[x].mi=1;
tree[x].cheng=1;
if (r<=mid) change(l1,head,mid,l,r,zl,y);
else if (l>mid) change(r1,mid+1,tail,l,r,zl,y);
else
{
change(l1,head,mid,l,mid,zl,y);
change(r1,mid+1,tail,mid+1,r,zl,y);
}

tree[x].ans=(tree[l1].ans*tree[r1].ans)%maxn;
}
int main()
{
freopen("segment.in","r",stdin);
freopen("segment.out","w",stdout);
tot=1;
tree[1].cheng=1;
tree[1].mi=1;
scanf("%lld",&q);
for (i=1;i<=q;i++)
{
scanf("%lld",&zl);
if (zl==0)
{
scanf("%lld%lld%lld",&x1,&y1,&z1);
y1--;
change(1,1,max1+max1,x1+max1,y1+max1,1,z1);
}
if (zl==1)
{
scanf("%lld%lld%lld",&x1,&y1,&z1);
y1--;
change(1,1,max1+max1,x1+max1,y1+max1,2,z1%(maxn-1));
}
if (zl==2)
{
scanf("%lld%lld",&x1,&y1);
y1--;
ans=1;
change(1,1,max1+max1,max1+x1,y1+max1,3,0);
printf("%lld\n",ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: