HDU4578-Transformation-多种区间修改、查询的线段树

二百行动漫码量,站内有很多大佬讲过了

/*I lv ya*/
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stdlib.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 1e5+5;
const ll md = 10007;
ll n,m;
ll tr[N<<2][3];///1 2 3
ll ta[N<<2][3];///add mul change
ll ls(ll p) {return p<<1;   }
ll rs(ll p) {return p<<1|1;  }
void push_up(ll p)
{
    ll lsp=ls(p);
    ll rsp=rs(p);
    for(int i=0;i<=2;i++)
    {
        tr[p][0]=(tr[lsp][0]+tr[rsp][0])%md;
        tr[p][1]=(tr[lsp][1]+tr[rsp][1])%md;
        tr[p][2]=(tr[lsp][2]+tr[rsp][2])%md;
    }
}
void build(ll p,ll pl,ll pr)
{
    ta[p][0]=ta[p][2]=0,ta[p][1]=1;
    if(pl==pr)
    {
        tr[p][0]=tr[p][1]=tr[p][2]=0;
        return ;
    }
    ll mid=(pl+pr)>>1;
    build(ls(p),pl,mid);
    build(rs(p),mid+1,pr);
    push_up(p);
}
void push_down(ll p,ll pl,ll pr)
{
    ll len=pr-pl+1;
    ll lsp=ls(p);
    ll rsp=rs(p);
    if(ta[p][2])
    {
        ta[lsp][2]=ta[rsp][2]=ta[p][2];

        tr[lsp][0]=(len-(len>>1))*ta[p][2]%md;
        tr[rsp][0]=(len>>1)*ta[p][2]%md;

        tr[lsp][1]=((len-(len>>1))*ta[p][2]%md)*ta[p][2]%md;
        tr[rsp][1]=((len>>1)*ta[p][2]%md)*ta[p][2]%md;

        tr[lsp][2]=((len-(len>>1))*ta[p][2]%md)*(ta[p][2]*ta[p][2]%md)%md;
        tr[rsp][2]=((len>>1)*ta[p][2]%md)*(ta[p][2]*ta[p][2]%md)%md;

        ta[lsp][0]=ta[rsp][0]=0;
        ta[lsp][1]=ta[rsp][1]=1;
        ta[p][2]=0;
    }
    if(ta[p][1]!=1)
    {
        ta[lsp][1]=ta[lsp][1]*ta[p][1]%md;
        ta[rsp][1]=ta[rsp][1]*ta[p][1]%md;

        ta[lsp][0]=ta[lsp][0]*ta[p][1]%md;
        ta[rsp][0]=ta[rsp][0]*ta[p][1]%md;

        tr[lsp][0]=tr[lsp][0]*ta[p][1]%md;
        tr[rsp][0]=tr[rsp][0]*ta[p][1]%md;

        tr[lsp][1]=(tr[lsp][1]*ta[p][1]%md)*ta[p][1]%md;
        tr[rsp][1]=(tr[rsp][1]*ta[p][1]%md)*ta[p][1]%md;

        tr[lsp][2]=(tr[lsp][2]*ta[p][1]%md)*(ta[p][1]*ta[p][1]%md)%md;
        tr[rsp][2]=(tr[rsp][2]*ta[p][1]%md)*(ta[p][1]*ta[p][1]%md)%md;

        ta[p][1]=1;
    }
    if(ta[p][0])
    {
        ta[lsp][0]=(ta[lsp][0]+ta[p][0])%md;
        ta[rsp][0]=(ta[rsp][0]+ta[p][0])%md;

        tr[lsp][2]=( tr[lsp][2] + 3*tr[lsp][1]*ta[p][0]%md + 3*ta[p][0]%md*(tr[lsp][0]*ta[p][0]%md)%md + (ta[p][0]*ta[p][0]%md)*(ta[p][0]*(len-(len>>1))%md))%md;
        tr[rsp][2]=( tr[rsp][2] + 3*tr[rsp][1]*ta[p][0]%md + 3*ta[p][0]%md*(tr[rsp][0]*ta[p][0]%md)%md + (ta[p][0]*ta[p][0]%md)*(ta[p][0]*(len>>1))%md)%md;

        tr[lsp][1]=( tr[lsp][1] + 2*tr[lsp][0]*ta[p][0]%md + (ta[p][0]*ta[p][0]%md)*(len-(len>>1))%md )%md;
        tr[rsp][1]=( tr[rsp][1] + 2*tr[rsp][0]*ta[p][0]%md + (ta[p][0]*ta[p][0]%md)*(len>>1)%md )%md;

        tr[lsp][0]=( tr[lsp][0] + (len-(len>>1))*ta[p][0]%md )%md;
        tr[rsp][0]=( tr[rsp][0] + (len>>1)*ta[p][0]%md )%md;

        ta[p][0]=0;
    }
}
void updata(ll L,ll R,ll v,ll p,ll pl,ll pr,ll op)
{
    ll len=pr-pl+1;
    if(L<=pl&&pr<=R)
    {
        if(op==1)
        {
            ta[p][0]=(ta[p][0]+v)%md;

            tr[p][2]=(tr[p][2]+3*tr[p][1]*v%md+3*(tr[p][0]*v%md)*v%md+((len*v%md)*(v*v%md)%md))%md;
            tr[p][1]=(tr[p][1]+2*tr[p][0]*v%md+(len*v%md)*v%md)%md;
            tr[p][0]=(tr[p][0]+len*v%md)%md;
        }
        else if(op==2)
        {
            ta[p][1]=ta[p][1]*v%md;
            ta[p][0]=ta[p][0]*v%md;

            tr[p][0]=tr[p][0]*v%md;
            tr[p][1]=(tr[p][1]*v%md)*v%md;
            tr[p][2]=(tr[p][2]*v%md)*(v*v%md)%md;
        }
        else if(op==3)
        {
            ta[p][2]=v;
            ta[p][1]=1;
            ta[p][0]=0;

            tr[p][0]=len*v%md;
            tr[p][1]=(len*v%md)*v%md;
            tr[p][2]=(len*v%md)*(v*v%md)%md;
        }
        return ;
    }
    push_down(p,pl,pr);
    ll mid=(pl+pr)>>1;
    if(L<=mid) updata(L,R,v,ls(p),pl,mid,op);
    if(R>mid) updata(L,R,v,rs(p),mid+1,pr,op);
    push_up(p);
}
ll query(ll L,ll R,ll v,ll p,ll pl,ll pr)
{
    if(L<=pl&&pr<=R)
    {
        return tr[p][v-1];
    }
    ll res=0;
    push_down(p,pl,pr);
    ll mid=(pl+pr)>>1;
    if(L<=mid) res=(res+query(L,R,v,ls(p),pl,mid))%md;
    if(R>mid) res=(res+query(L,R,v,rs(p),mid+1,pr))%md;
    return res%md;
}
void solve()
{
    memset(ta,0,sizeof(ta));
    memset(tr,0,sizeof(tr));
    build(1,1,n);
    while(m--)
    {
        ll op,x,y,c;
        cin>>op>>x>>y>>c;
        if(op==1)
        {
            updata(x,y,c,1,1,n,1);
        }
        else if(op==2)
        {
            updata(x,y,c,1,1,n,2);
        }
        else if(op==3)
        {
            updata(x,y,c,1,1,n,3);
        }
        else
        {
            cout<<query(x,y,c,1,1,n)<<endl;;
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL),cout.tie(NULL);
    int _;
    while(cin>>n>>m)
    {
        if(n==0&&m==0) break;
        solve();
    }
    return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值