LOJ #3043. 「ZJOI2019」线段树 线段树+分类讨论
大大大分类讨论,思路还是非常巧妙的.
code:
#include <bits/stdc++.h> #define ll long long #define lson now<<1 #define rson now<<1|1 #define N 100008 #define mod 998244353 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,m,cur; ll f[N<<3],g[N<<3],SUM[N<<3],qp[N],mf[N<<3],mg[N<<3]; void markf(int now,int v) { f[now]=(ll)f[now]*qp[v]%mod; SUM[now]=(ll)SUM[now]*qp[v]%mod; mf[now]+=v; } void markg(int now,int v) { g[now]=(ll)g[now]*qp[v]%mod; mg[now]+=v; } void pushdown(int now) { if(mf[now]) { markf(lson,mf[now]); markf(rson,mf[now]); mf[now]=0; } if(mg[now]) { markg(lson,mg[now]); markg(rson,mg[now]); mg[now]=0; } } void pushup(int now) { SUM[now]=(ll)(SUM[lson]+SUM[rson]+f[now])%mod; } void build(int l,int r,int now) { f[now]=0,g[now]=1; if(l==r) return; int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); } void update(int l,int r,int now,int L,int R) { pushdown(now); if(l>=L&&r<=R) { // 1 类点 f[now]=(ll)(f[now]+qp[cur-1])%mod; markf(lson,1),markf(rson,1); pushup(now); return; } int mid=(l+r)>>1; if(L<=mid&&R>mid) { update(l,mid,lson,L,R); update(mid+1,r,rson,L,R); } else if(L<=mid) { update(l,mid,lson,L,R); int p=rson; pushdown(p); markf(p<<1,1),markf(p<<1|1,1); markg(p<<1,1),markg(p<<1|1,1); f[p]=(ll)(f[p]+qp[cur-1]-g[p]+mod)%mod; g[p]=(ll)(g[p]+g[p])%mod; pushup(p); } else { update(mid+1,r,rson,L,R); int p=lson; pushdown(p); markf(p<<1,1),markf(p<<1|1,1); markg(p<<1,1),markg(p<<1|1,1); f[p]=(ll)(f[p]+qp[cur-1]-g[p]+mod)%mod; g[p]=(ll)(g[p]+g[p])%mod; pushup(p); } // 2 类点 // g[now]=(ll)(g[now]+qp[cur-1])%mod; pushup(now); } int main() { // setIO("input"); qp[0]=1; for(int i=1;i<N;++i) qp[i]=(ll)qp[i-1]*2%mod; scanf("%d%d",&n,&m); build(1,n,1); for(int i=1;i<=m;++i) { int op,l,r; scanf("%d",&op); if(op==1) { scanf("%d%d",&l,&r),++cur,update(1,n,1,l,r); } else { printf("%lld\n",SUM[1]); } } return 0; }