题面

传送门

题解

考场上就这么一道会做的其它连暴力都没打……活该爆炸……

首先我们得看出问题的本质:有\(m\)个操作,总共\(2^m\)种情况分别对应每个操作是否执行,求这\(2^m\)棵线段树上\(tag\)为\(1\)的节点个数

那么很明显得转化为每个节点在多少种情况里\(tag\)为\(1\)

对于一个操作\([ql,qr]\),我们把线段树上所有节点分成四类考虑

1.如果\(ql\leq l\&\&qr\geq r\),且该节点被访问到,那么不管之前操作序列怎么样,只要执行了当前操作它必为\(1\),所以它的值加上\(2^t\),其中\(t\)为已经执行的操作数目

2.如果节点没有被访问到过,那么这个操作是否执行都对它们的\(tag\)没有影响,所以它们的值乘\(2\)

3.如果\([ql,qr]\cap[l,r]\neq \emptyset\)且不属于\(1\),那么如果当前操作执行它们的\(tag\)显然全没了,所以它们的值不变

4.还有一种情况\([ql,qr]\cap [l,r]=\emptyset\),且当前节点的父亲属于\(3\),但是当前节点不属于\(1\)。这种情况下当前节点的值要加上\(f_i\),其中\(f_i\)表示的是“能够使当前节点到根的所有节点中存在\(tag\)为\(1\)的点的序列个数”

先不考虑\(f_i\)怎么维护。那么我们只要在线段树上遍历区间,对应地打上给节点加上值(比如\(1\)),给节点打乘法标记就行了。全局的答案可以先减去所有遍历到的节点的答案,乘上\(2\)之后再把遍历到的节点的答案加上去就好了

然后关键是\(f_i\)还得维护啊……还是得分类讨论……

1.如果\(ql\leq l\&\&qr\geq r\),不管当前节点是否被访问过。因为当前操作执行之后它们到根节点的路径上显然会有\(tag\)为\(1\),所以这些节点每一个都要加上\(2^{t-1}\)

2.如果是之前的\(3\)情况,那么显然根节点到它的所有\(tag\)都没了,所以\(f_i\)不变

3.除此之外的所有情况,包括之前的\(4\),显然当前操作不管是否执行都对它们的\(f_i\)没有影响,所以它们的\(f_i\)都要乘\(2\)

然后没有然后了

//minamoto
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e5+5,P=998244353;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
struct node{
node *lc,*rc;int sv,tv,sf,taf,tmf;
node(){tv=tmf=1;}
inline void pmf(R int x){sf=mul(sf,x),taf=mul(taf,x),tmf=mul(tmf,x);}
inline void paf(R int x){sf=add(sf,x),taf=add(taf,x);}
inline void pv(R int x){tv=mul(tv,x),sv=mul(sv,x);}
inline void pd(){
if(tv)lc->pv(tv),rc->pv(tv),tv=1;
if(tmf)lc->pmf(tmf),rc->pmf(tmf),tmf=1;
if(taf)lc->paf(taf),rc->paf(taf),taf=0;
}
}pool[N<<2],*rt;int num;
inline node *newnode(){return &pool[num++];}
void build(node* &p,int l,int r){
p=newnode();if(l==r)return;
int mid=(l+r)>>1;
build(p->lc,l,mid),build(p->rc,mid+1,r);
}
int res,ans,ql,qr,t,op;
void update(node *p,int l,int r){
if(ql<=l&&qr>=r){
ans=dec(ans,p->sv);
p->sv=add(p->sv,t),p->tv=mul(p->tv,2),p->paf(t);
res=add(res,p->sv);
return;
}
if(ql>r||qr<l){
ans=dec(ans,p->sv);
p->sv=add(p->sv,p->sf),p->pmf(2),p->tv=mul(p->tv,2);
res=add(res,p->sv);
return;
}
int mid=(l+r)>>1;p->pd();
ans=dec(ans,p->sv),res=add(res,p->sv);
update(p->lc,l,mid),update(p->rc,mid+1,r);
}
int n,m;
int main(){
// freopen("testdata.in","r",stdin);
n=read(),m=read(),t=1;
build(rt,1,n);
while(m--){
op=read();
if(op&2)print(ans);
else ql=read(),qr=read(),res=0,update(rt,1,n),ans=add(mul(ans,2),res),t=mul(t,2);
}
return Ot(),0;
}

洛谷P5280 [ZJOI2019]线段树(线段树)的更多相关文章

  1. 洛谷P5280 [ZJOI2019]线段树

      https://www.luogu.org/problemnew/show/P5280 省选的时候后一半时间开这题,想了接近两个小时的各种假做法,之后想的做法已经接近正解了,但是有一些细节问题理不 ...

  2. 洛谷 P5280 - [ZJOI2019]线段树(线段树+dp,神仙题)

    题面传送门 神仙 ZJOI,不会做啊不会做/kk Sooke:"这八成是考场上最可做的题",由此可见 ZJOI 之毒瘤. 首先有一个非常显然的转化,就是题目中的"将线段树 ...

  3. 洛谷P5280 [ZJOI2019]线段树 [线段树,DP]

    传送门 无限Orz \(\color{black}S\color{red}{ooke}\)-- 思路 显然我们不能按照题意来每次复制一遍,而多半是在一棵线段树上瞎搞. 然后我们可以从\(modify\ ...

  4. 洛谷 P3373 【模板】线段树 2

    洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...

  5. 洛谷P3372 【模板】线段树 1

    P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷 ...

  6. 洛谷P4891 序列(势能线段树)

    洛谷题目传送门 闲话 考场上一眼看出这是个毒瘤线段树准备杠题,发现实在太难调了,被各路神犇虐哭qwq 考后看到各种优雅的暴力AC......宝宝心里苦qwq 思路分析 题面里面是一堆乱七八糟的限制和性 ...

  7. 洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)

    To 洛谷.2574 XOR的艺术 题目描述 AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的 ...

  8. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

  9. Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)

    题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...

随机推荐

  1. 23.Merge k Sorted Lists (Array, Queue; Sort)

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 思 ...

  2. kafka常用运维命令

    列出所有topic:bin/kafka-topics.sh --zookeeper localhost:2181 --list说明:其实就是去检查zk上节点的/brokers/topics子节点,打印 ...

  3. CloudStack 4.1快照测试

    目前4.1只支持存储快照,4.2能支持内快照 1. 选中实例 2. 查看实例卷 3. 创建快照 4. 通过快照创建模板 5. 查看通过快照创建的模板 6. 通过快照创建模板生成的实例 7. 自动定制创 ...

  4. Qt's Undo Framework

    Overview of Qt's Undo Framework Introduction Qt's Undo Framework is an implementation of the Command ...

  5. style="width:100px" 和width=100 异同

    异: 1.width属性不是每个元素都支持的,一般就table和body支持. 2.style="width: 100px"是CSS样式. 2.1.CSS样式有多种方式设置,直接写 ...

  6. 初次使用Xcode遇到的问题及解决方法

    使用的是Xcode 5.1.1 版本 1.调整字体 点击左上角的Xcode->Preference->Font  & colors .需要注意到是,只有选择下图中黑色框框里面的一行 ...

  7. msys2 + clion安装所需的mingw64编译环境

    pacman -S mingw-w64-x86_64-toolchain 输出结果为: $ pacman -S mingw-w64-x86_64-toolchain:: 在组 mingw-w64-x8 ...

  8. jquery对属性和特性的操作

    attribute(特性)和property(属性)是两个不同的概念.attribute表示HTML文档节点的特性,property表示DOM元素的属性 这些属性例如selectedIndex, ta ...

  9. CodeForces 686A Free Ice Cream (水题模拟)

    题意:给定初始数量的冰激凌,然后n个操作,如果是“+”,那么数量就会增加,如果是“-”,如果现有的数量大于等于要减的数量,那么就减掉,如果小于, 那么孩子就会离家.问你最后剩下多少冰激凌,和出走的孩子 ...

  10. python使用smtplib和email发送腾讯企业邮箱邮件

    公司每天要发送日报,最近没事搞了一下如何自动发邮件,用的是腾讯企业邮箱,跟大家分享一下我的研究过程吧. 以前弄的发邮件的是用qq邮箱发的,当时在网上查资料最后达到了能发图片,网页,自定义收件人展示,主 ...