[ZJOI2019]线段树

Posted miracevin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZJOI2019]线段树相关的知识,希望对你有一定的参考价值。

[ZJOI2019]线段树 

https://www.luogu.org/blog/Sooke/solution-p5280

f不够,加上g

g的转移?要特别注意没有直接访问的点。分5类点

大力分类讨论即可。

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^‘0‘)
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch==-)&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+0);}
template<class T>il void ot(T x){if(x<0) putchar(-),x=-x;output(x);putchar( );}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar(
);}

namespace Miracle{
const int N=1e5+5;
const int mod=998244353;
int n,m;
int ad(int x,int y){
    return x+y>=mod?x+y-mod:x+y;
}
int mul(int x,int y){
    return (ll)x*y%mod;
}
struct node{
    int f,g,sumf;
    int mf,mg;
}t[4*N];
int T;
void pushup(int x){
    t[x].sumf=ad(ad(t[x<<1].sumf,t[x<<1|1].sumf),t[x].f);
}
void build(int x,int l,int r){
    if(l==r){
        t[x].g=1;t[x].f=0;t[x].mf=1;t[x].mg=1;
        return;
    }
    t[x].g=1;t[x].mf=1;t[x].mg=1;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
}
void pushdown(int x){
    for(reg i=0;i<=1;++i){
        int son=(x<<1)|i;
        t[son].mf=mul(t[son].mf,t[x].mf);
        t[son].f=mul(t[son].f,t[x].mf);
        t[son].sumf=mul(t[son].sumf,t[x].mf);
        
        t[son].mg=mul(t[son].mg,t[x].mg);
        t[son].g=mul(t[son].g,t[x].mg);
    }
    t[x].mf=1;t[x].mg=1;
}
void upda(int x,int l,int r,int L,int R){
    if(L<=l&&r<=R){//2
        t[x].sumf=ad(mul(ad(t[x].sumf,mod-t[x].f),2),ad(t[x].f,T));
        t[x].f=ad(t[x].f,T);
        t[x].mf=mul(t[x].mf,2);//4
//        cout<<" f "<<t[x].f<<" sumf "<<t[x].sumf<<endl;
        return;
    }
    t[x].g=ad(t[x].g,T);
    pushdown(x);//1
    if(L<=mid&&mid<R){
        upda(x<<1,l,mid,L,R);
        upda(x<<1|1,mid+1,r,L,R);
        
    }else if(L<=mid){
        upda(x<<1,l,mid,L,R);
        
        int son=x<<1|1;//3
        t[son].sumf=ad(mul(ad(t[son].sumf,mod-t[son].f),2),ad(t[son].f,ad(T,mod-t[son].g)));
        t[son].f=ad(t[son].f,ad(T,mod-t[son].g));
        
//        cout<<" f "<<t[son].f<<" sumf "<<t[son].sumf<<" g "<<t[son].g<<endl;
        t[son].g=mul(t[son].g,2);
        
        t[son].mf=mul(t[son].mf,2);//5
        t[son].mg=mul(t[son].mg,2);
//        cout<<son<<endl;
        
        
    }else{
        upda(x<<1|1,mid+1,r,L,R);
        
        int son=(x<<1);//3
        t[son].sumf=ad(mul(ad(t[son].sumf,mod-t[son].f),2),ad(t[son].f,ad(T,mod-t[son].g)));
        t[son].f=ad(t[son].f,ad(T,mod-t[son].g));
        t[son].g=mul(t[son].g,2);
        
        t[son].mf=mul(t[son].mf,2);//5
        t[son].mg=mul(t[son].mg,2);
    }
    pushup(x);
}
int main(){
    rd(n);rd(m);
    build(1,1,n);
    int op,l,r;
    T=1;
    while(m--){
        rd(op);
        if(op==1){
            rd(l);rd(r);
            upda(1,1,n,l,r);
            T=mul(T,2);
        }else{
            printf("%d
",t[1].sumf);
        }
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/4/10 15:37:22
*/

 

以上是关于[ZJOI2019]线段树的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P5280 [ZJOI2019]线段树

「ZJOI2019」线段树

[ZJOI2019]线段树

[ZJOI2019]线段树

Luogu5280 [ZJOI2019] 线段树 线段树

[ZJOI2019]线段树