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

来源:互联网 发布:淘宝广场舞服装春装 编辑:程序博客网 时间:2024/04/30 16:06

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 longusing 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,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);        }    }}
阅读全文
0 0
原创粉丝点击