• [Luogu5280][ZJOI2019]线段树(线段树+DP)


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

    首先想到对线段树上每个点分别维护有多少棵线段树在它上有标记(f[]),然后想到对于每个操作,根据转移的不同分成5种点。

    为了满足第三类点的转移要求,再维护g[],转移类似分类讨论即可。

    最后发现前三类点是$O(log n)$级别的,后两类点可以通过打标记实现。于是就做完了。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define ls (x<<1)
     4 #define rs (ls|1)
     5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     6 using namespace std;
     7 
     8 const int N=2000010,mod=998244353;
     9 int n,m,k=1,op,l,r,f[N],g[N],tf[N],tg[N],sf[N];
    10 
    11 int add(int x,int y){ return x+y>=mod ? x+y-mod : x+y; }
    12 int sub(int x,int y){ return x-y<0 ? x-y+mod : x-y; }
    13 
    14 void upd(int x){ sf[x]=add(f[x],add(sf[ls],sf[rs])); }
    15 void pushf(int x,int k){ f[x]=1ll*f[x]*k%mod; tf[x]=1ll*tf[x]*k%mod; sf[x]=1ll*sf[x]*k%mod; }
    16 void pushg(int x,int k){ g[x]=1ll*g[x]*k%mod; tg[x]=1ll*tg[x]*k%mod; }
    17 
    18 void push(int x){
    19     if (tf[x]!=1) pushf(ls,tf[x]),pushf(rs,tf[x]),tf[x]=1;
    20     if (tg[x]!=1) pushg(ls,tg[x]),pushg(rs,tg[x]),tg[x]=1;
    21 }
    22 
    23 void build(int x,int L,int R){
    24     g[x]=tf[x]=tg[x]=1;
    25     if (L==R) return;
    26     int mid=(L+R)>>1;
    27     build(ls,L,mid); build(rs,mid+1,R);
    28 }
    29 
    30 void mdf(int x,int L,int R,int l,int r){
    31     push(x);
    32     if (L==l && r==R){ f[x]=add(f[x],k); pushf(ls,2); pushf(rs,2); upd(x); return; }
    33     int mid=(L+R)>>1; g[x]=add(g[x],k);
    34     if (r<=mid){
    35         mdf(ls,L,mid,l,r); push(rs); f[rs]=add(f[rs],sub(k,g[rs])); g[rs]=add(g[rs],g[rs]);
    36         pushf(rs<<1,2); pushf((rs<<1)|1,2); pushg(rs<<1,2); pushg((rs<<1)|1,2); upd(rs);
    37     }else if (l>mid){
    38         mdf(rs,mid+1,R,l,r); push(ls); f[ls]=add(f[ls],sub(k,g[ls])); g[ls]=add(g[ls],g[ls]);
    39         pushf(ls<<1,2); pushf((ls<<1)|1,2); pushg(ls<<1,2); pushg((ls<<1)|1,2); upd(ls);
    40     }else mdf(ls,L,mid,l,mid),mdf(rs,mid+1,R,mid+1,r);
    41     upd(x);
    42 }
    43 
    44 int main(){
    45     freopen("segment.in","r",stdin);
    46     freopen("segment.out","w",stdout);
    47     scanf("%d%d",&n,&m); build(1,1,n);
    48     rep(i,1,m){
    49         scanf("%d",&op);
    50         if (op==1) scanf("%d%d",&l,&r),mdf(1,1,n,l,r),k=add(k,k);
    51             else printf("%d
    ",sf[1]);
    52     }
    53     return 0;
    54 }
  • 相关阅读:
    [引]Windows Server 2003 : 服务器群集
    周国平:(爱情)永远未完成
    企业管理常用缩写术语之中英文对照表(含解释)
    微软相关中文网站
    陈安之:NAC神经链调正术
    学会不要再争吵
    Oracle基础学习四:字符串 数字 日期 等 相关函数
    贪多嚼不烂
    frameset 框架传值点滴
    陈安之成功的十个关键
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10706408.html
Copyright © 2020-2023  润新知