传送门


无限Orz \(\color{black}S\color{red}{ooke}\)……


思路

显然我们不能按照题意来每次复制一遍,而多半是在一棵线段树上瞎搞。

然后我们可以从\(modify\)函数入手,寻找一些性质。

(盗一张Sooke的图)

可以发现每次\(modify\)之中,所有节点都可以被分成5类:

  1. 白色:经过而且标记全都被下传的点。
  2. 黑色:打上标记的点。
  3. 灰色:在修改区域内但不会被经过的点。
  4. 橙色:可以享受到来自上方标记的滋润的点。
  5. 黄色:半毛钱关系都没有的点……

分类之后,可以发现:如果DP的话,所有同一类型的点的转移方程都是基本相同的。

于是考虑DP:很自然地,想到设\(f_i\)表示在所有情况中\(tag_i=1\)的情况个数。

那么有转移方程:

\[f_i=\begin{cases}
f_i&,white\\
f_i+2^t&,black\\
2f_i&,grey\\
2f_i&,yellow\\
?????&,orange
\end{cases}
\]

你发现橙色点还要根据上方点是否有标记来转移,烦死了。

于是再一次很自然地,想到设\(g_i\)表示在所有情况中\(i\rightarrow root\)路径上存在\(tag_x=1\)的情况个数。

那么有转移方程:

\[g_i=\begin{cases}
g_i&,white\\
g_i+2^t&,black\\
g_i+2^t&,grey\\
2g_i&,yellow\\
2g_i&,orange
\end{cases}
\]

然后终于可以得到:

\[f_i=f_i+g_i,orange
\]

大功告成!

显然白色、黑色、橙色暴力转移,灰色、黄色随便维护下懒标记即可。

最后答案是\(\sum_i f_i\),也是在线段树上很好统计的。


代码

  1. #include<bits/stdc++.h>
  2. clock_t t=clock();
  3. namespace my_std{
  4. using namespace std;
  5. #define pii pair<int,int>
  6. #define fir first
  7. #define sec second
  8. #define MP make_pair
  9. #define rep(i,x,y) for (int i=(x);i<=(y);i++)
  10. #define drep(i,x,y) for (int i=(x);i>=(y);i--)
  11. #define go(x) for (int i=head[x];i;i=edge[i].nxt)
  12. #define templ template<typename T>
  13. #define sz 202020
  14. #define mod 998244353ll
  15. typedef long long ll;
  16. typedef double db;
  17. mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  18. templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
  19. templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
  20. templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
  21. templ inline void read(T& t)
  22. {
  23. t=0;char f=0,ch=getchar();double d=0.1;
  24. while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
  25. while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
  26. if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
  27. t=(f?-t:t);
  28. }
  29. template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
  30. char __sr[1<<21],__z[20];int __C=-1,__zz=0;
  31. inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
  32. inline void print(register int x)
  33. {
  34. if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
  35. while(__z[++__zz]=x%10+48,x/=10);
  36. while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
  37. }
  38. void file()
  39. {
  40. #ifndef ONLINE_JUDGE
  41. freopen("a.in","r",stdin);
  42. #endif
  43. }
  44. inline void chktime()
  45. {
  46. #ifndef ONLINE_JUDGE
  47. cout<<(clock()-t)/1000.0<<'\n';
  48. #endif
  49. }
  50. #ifdef mod
  51. ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
  52. ll inv(ll x){return ksm(x,mod-2);}
  53. #else
  54. ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
  55. #endif
  56. // inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
  57. }
  58. using namespace my_std;
  59. int n,m;
  60. ll pow2;
  61. ll f[sz<<2],g[sz<<2],fMul[sz<<2],gAdd[sz<<2],gMul[sz<<2];
  62. ll S[sz<<2];
  63. #define ls k<<1
  64. #define rs k<<1|1
  65. #define lson ls,l,mid
  66. #define rson rs,mid+1,r
  67. void mulf(int k,ll w){(f[k]*=w)%=mod;(fMul[k]*=w)%=mod;(S[k]*=w)%=mod;}
  68. void mulg(int k,ll w){(g[k]*=w)%=mod;(gMul[k]*=w)%=mod;(gAdd[k]*=w)%=mod;}
  69. void addg(int k,ll w){(g[k]+=w)%=mod;(gAdd[k]+=w)%=mod;}
  70. void pushdown(int k)
  71. {
  72. mulg(ls,gMul[k]);mulg(rs,gMul[k]);gMul[k]=1;
  73. addg(ls,gAdd[k]);addg(rs,gAdd[k]);gAdd[k]=0;
  74. mulf(ls,fMul[k]);mulf(rs,fMul[k]);fMul[k]=1;
  75. }
  76. void pushup(int k){S[k]=(S[ls]+S[rs]+f[k])%mod;}
  77. void modify1(int k,int l,int r,int x,int y) // white,black,grey
  78. {
  79. pushdown(k);
  80. int mid=(l+r)>>1;
  81. if (x<=l&&r<=y) // black
  82. {
  83. (f[k]+=pow2)%=mod;
  84. (g[k]+=pow2)%=mod;
  85. addg(ls,pow2);addg(rs,pow2); // grey
  86. mulf(ls,2);mulf(rs,2); // grey
  87. pushup(k);
  88. return;
  89. }
  90. // white (do nothing)
  91. if (x<=mid) modify1(lson,x,y);
  92. if (y>mid) modify1(rson,x,y);
  93. pushup(k);
  94. }
  95. void modify2(int k,int l,int r,int x,int y) // orange,yellow
  96. {
  97. pushdown(k);
  98. if (x<=l&&r<=y) // orange
  99. {
  100. (f[k]+=g[k])%=mod;(g[k]+=g[k])%=mod;
  101. mulg(ls,2);mulg(rs,2); // yellow
  102. mulf(ls,2);mulf(rs,2); // yellow
  103. pushup(k);
  104. return;
  105. }
  106. int mid=(l+r)>>1;
  107. if (x<=mid) modify2(lson,x,y);
  108. if (y>mid) modify2(rson,x,y);
  109. pushup(k);
  110. }
  111. void build(int k,int l,int r)
  112. {
  113. f[k]=g[k]=0;
  114. fMul[k]=gMul[k]=1;gAdd[k]=0;
  115. if (l==r) return;
  116. int mid=(l+r)>>1;
  117. build(lson);build(rson);
  118. }
  119. int main()
  120. {
  121. file();
  122. read(n,m);
  123. build(1,1,n);
  124. int z,x,y;
  125. pow2=1;
  126. while (m--)
  127. {
  128. read(z);
  129. if (z==2) printf("%lld\n",S[1]);
  130. else
  131. {
  132. read(x,y);
  133. modify1(1,1,n,x,y);
  134. if (x!=1) modify2(1,1,n,1,x-1);
  135. if (y!=n) modify2(1,1,n,y+1,n);
  136. (pow2*=2)%=mod;
  137. }
  138. }
  139. return 0;
  140. }

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

  1. 洛谷P5280 [ZJOI2019]线段树

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

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

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

  3. 洛谷P5280 [ZJOI2019]线段树(线段树)

    题面 传送门 题解 考场上就这么一道会做的其它连暴力都没打--活该爆炸-- 首先我们得看出问题的本质:有\(m\)个操作,总共\(2^m\)种情况分别对应每个操作是否执行,求这\(2^m\)棵线段树上 ...

  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. H5网页后在返回到微信公众平台自定义菜单

    <p class="success">订阅成功!</p> <div class="btn" @click="finish ...

  2. OpenStack-Neutron(5)

    一. Neutron 概述 SDN(software-defined networking)软件定义网络,其所具有的灵活性和自动化优势使其成为云时代网络管理的主流. Neutron的设计目标是实现“网 ...

  3. MySQL-ERROR 2003

    1.首先安装mysqld服务器,输入命令:mysqld --install 2.输入命令:mysqld --initialize-insecure 3.输入命令:net start mysql

  4. Django------多表操作

    一. 创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一的 ...

  5. opencv 增强现实(二):特征点匹配

    import cv2 as cv import numpy as np # def draw_keypoints(img, keypoints): # for kp in keypoints: # x ...

  6. File相关操作

    文件操作 流关闭方法 public static void closeQuietly(Closeable closable) { if (null == closable) { return; } t ...

  7. java实现sftp客户端上传文件夹的功能

    使用的jar: <dependencies> <dependency> <groupId>jsch</groupId> <artifactId&g ...

  8. GWAS: 曼哈顿图,QQ plot 图,膨胀系数( manhattan、Genomic Inflation Factor)

    画曼哈顿图和QQ plot 首推R包“qqman”,简约方便.下面具体介绍以下. 一.画曼哈顿图 install.packages("qqman") library(qqman) ...

  9. Matlab调用Java类

    第一步:定位Matlab中Java环境的ext目录 新建一个M script文件,或者直接在Matlab的交互式命令行中输入: >> disp(java.lang.System.getPr ...

  10. Spark Java API 之 CountVectorizer

    Spark Java API 之 CountVectorizer 由于在Spark中文本处理与分析的一些机器学习算法的输入并不是文本数据,而是数值型向量.因此,需要进行转换.而将文本数据转换成数值型的 ...