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;
}

浙公网安备 33010602011771号