容易发现相当于求2m种操作序列所得的每种线段树tag数量之和。显然考虑每个点的贡献,也即有多少种方案会使该点上有tag。可以将点分为四类:

  1.修改时被经过且有儿子被修改的节点

  2.修改时被经过且没有儿子被修改的节点

  3.修改时未被经过且有兄弟被修改的节点

  4.修改时未被经过且没有兄弟被修改的节点

  考虑一次修改对这些点的影响。设该次操作之前已进行p次修改。易得:

  1.方案数不变

  2.方案数+2p

  3.方案数+修改前该点到根路径(包括该点自身)上有tag的方案数

  4.方案数*2

  只要考虑维护3类点所需的东西即可。对此易得:

  1.方案数不变

  2.方案数+2p

  3.方案数*2

  4.与其最近的非4类点祖先相同

  维护两棵线段树即可。其中第一棵可以转化为维护概率来避免打lazy标记,当然并不重要。

  注意维护3类点取出方案数时需要pushdown,并且对此处的pushdown需要小心是否有写丑导致四倍空间不够用。

  upd:上一句可以划掉,突然发现自己莫名其妙的把一个log硬是写成两个log了……两棵线段树看成一棵完全没问题,顺便pushdown一下就好。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define P 998244353
#define N 100010
#define inv 499122177
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,m,tree[N<<2],p[N],p2[N],stk[N],ans;
int val[N<<2],taga[N<<2],tagm[N<<2];
void del(int x){ans=(ans+P-x)%P;}
void ins(int x){ans=(ans+x)%P;}
void updatea(int k,int x)
{
val[k]=(val[k]+x)%P;
taga[k]=(taga[k]+x)%P;
}
void downa(int k)
{
updatea(k<<1,taga[k]);
updatea(k<<1|1,taga[k]);
taga[k]=0;
}
void updatem(int k,int x)
{
val[k]=1ll*val[k]*x%P;
tagm[k]=1ll*tagm[k]*x%P;
taga[k]=1ll*taga[k]*x%P;
}
void downm(int k)
{
updatem(k<<1,tagm[k]);
updatem(k<<1|1,tagm[k]);
tagm[k]=1;
}
void add(int k,int l,int r,int x,int y,int p)
{
if (l==x&&r==y) {updatea(k,p);return;}
if (tagm[k]!=1) downm(k);
if (taga[k]!=0) downa(k);
int mid=l+r>>1;
if (y<=mid)
{
updatem(k<<1|1,2);
add(k<<1,l,mid,x,y,p);
}
else if (x>mid)
{
updatem(k<<1,2);
add(k<<1|1,mid+1,r,x,y,p);
}
else add(k<<1,l,mid,x,mid,p),add(k<<1|1,mid+1,r,mid+1,y,p);
}
int query(int k)
{
int top=0;
for (int i=k;i;i>>=1) stk[++top]=i;
for (int i=top;i>1;i--)
{
if (tagm[stk[i]]!=1) downm(stk[i]);
if (taga[stk[i]]!=0) downa(stk[i]);
}
return val[k];
}
void modify(int k,int l,int r,int x,int y,int p)
{
if (l==x&&r==y)
{
del(tree[k]);
tree[k]=1ll*(tree[k]+1)*inv%P;
ins(tree[k]);
return;
}
if (tagm[k]!=1) downm(k);
if (taga[k]!=0) downa(k);
del(tree[k]);
tree[k]=1ll*tree[k]*inv%P;
ins(tree[k]);
int mid=l+r>>1;
if (y<=mid)
{
del(tree[k<<1|1]);
tree[k<<1|1]=1ll*(tree[k<<1|1]+1ll*val[k<<1|1]*p%P)*inv%P;
ins(tree[k<<1|1]);
modify(k<<1,l,mid,x,y,p);
}
else if (x>mid)
{
del(tree[k<<1]);
tree[k<<1]=1ll*(tree[k<<1]+1ll*val[k<<1]*p%P)*inv%P;
ins(tree[k<<1]);
modify(k<<1|1,mid+1,r,x,y,p);
}
else modify(k<<1,l,mid,x,mid,p),modify(k<<1|1,mid+1,r,mid+1,y,p);
}
void fill(int k,int l,int r){tagm[k]=1;if (l==r) return;fill(k<<1,l,l+r>>1);fill(k<<1|1,(l+r>>1)+1,r);}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
p[0]=1;for (int i=1;i<=m;i++) p[i]=(p[i-1]<<1)%P;
p2[0]=1;for (int i=1;i<=m;i++) p2[i]=1ll*p2[i-1]*inv%P;
int cnt=0;fill(1,1,n);
for (int _=1;_<=m;_++)
{
int op=read();
if (op==1)
{
int l=read(),r=read();
modify(1,1,n,l,r,p2[cnt]);
add(1,1,n,l,r,p[cnt]);
cnt++;
}
else printf("%d\n",1ll*ans*p[cnt]%P);
}
return 0;
}

  

Luogu5280 ZJOI2019线段树(线段树)的更多相关文章

  1. HDU 5877 dfs+ 线段树(或+树状树组)

    1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au, ...

  2. 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))

    函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...

  3. BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3196 可以处理区间问题的平衡树. 3196: Tyvj 1730 二逼平衡树 Time Lim ...

  4. [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】

    题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...

  5. BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)

    题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...

  6. 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

    如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...

  7. HDOJ 4417 - Super Mario 线段树or树状数组离线处理..

    题意: 同上 题解: 抓着这题作死的搞~~是因为今天练习赛的一道题.SPOJ KQUERY.直到我用最后一种树状数组通过了HDOJ这题后..交SPOJ的才没超时..看排名...时间能排到11名了..有 ...

  8. hdu 4836 The Query on the Tree(线段树or树状数组)

    The Query on the Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  9. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...

  10. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

随机推荐

  1. Charles 抓包工具安装和采坑记录

    Charles 抓包工具安装和采坑记录 网络抓包是解决网络问题的第一步,也是网络分析的基础.网络出现问题,第一步肯定是通过抓包工具进行路径分析,看哪一步出现异常.做网络爬虫,第一步就是通过抓包工具对目 ...

  2. LNK2022: 元数据操作失败(8013118D): 重复类型(FactoryContext)中的布局信息不一致: (0x02000230)

    1. c++项目 A 编译成A.lib文件 2. c++项目B引用这个A.lib文件 3. A项目存在一个类跟B项目一样,但是A项目其他文件需要这个类里面的某些东西,我将不需要的全部注释掉,然后编译A ...

  3. 无线网络中信噪比(SNR)计算

    信噪比(S/N)=log[信号功率密度/噪声功率密度] a =log[信号功率密度]-log[噪声功率密度] 例如,接收端的信号功率密度为-63dBm,噪声的信号功率密度为-95dBm,则: 信噪比( ...

  4. github/gitlab同时管理多个ssh key

    之前一直用github,但是github有一个不好的地方,要是创建私有的项目的话需要付费,而gitlab上则可以免费创建管理私有的项目.由于最近想把自己论文的一些东西整理一下,很多东西还是不方便公开, ...

  5. 关于XLL加载项动态加载、卸载的演示及XLL函数自定义类型注册的演示

    1.在XLL中,把函数定义成不同的类型,在Excel中的实际效果也不同,具体如下: pxMacroType value                                          ...

  6. 现代程序设计 homework-10

    经过大半学期的学习和练习, 我们把学到的东西综合起来. 通过<现代程序设计>这门课,自己的确学到了好多东西.其实并不是说讲课有多棒,一是因为讲课的次数其实并不多,二是讲课的内容其实感觉并没 ...

  7. [2017BUAA软工助教]个人项目准备工作

    BUAA软工个人项目准备工作 零.注册Github个人账号(你不会没有吧..) 这是Git的使用教程: http://www.cnblogs.com/schaepher/p/5561193.html ...

  8. HDU 3947 Assign the task

    http://acm.hdu.edu.cn/showproblem.php?pid=3974 Problem Description There is a company that has N emp ...

  9. 09-babel

    这个是解析我们es6的代码的,为什么要用它呢,因为对于一些ie浏览器,甚至FF浏览器,低版本的还不能识别我们的es6代码,那么vue里面好多还让我们去写es6的代码,这个时候我们就可以用babel这个 ...

  10. Redis教程(Windows)

    安装 1)下载redis压缩包并  , 推荐地址:https://github.com/MSOpenTech/redis/releases Redis 支持 32 位和 64 位.这个需要根据你系统平 ...