题目链接

BZOJ4785

题解

肝了一个下午QAQ没写过二维线段树还是很难受

首先题目中的树状数组实际维护的是后缀和,这一点凭分析或经验或手模观察可以得出

在\(\mod 2\)意义下,我们实际求出的区间和是\([l - 1,r - 1]\),和\([l,r]\)唯一不同的就在于\(l - 1\)和\(r\)

所以每个询问实际是询问两个位置值相同的概率

我们把询问看做二元组\((a,b)\),其中\(a \le b\),我们要维护\((a,b)\)不同的概率【至于为什么是不同而不是相同,等下说】

初始概率都为\(0\)

对于修改操作\([l,r]\)

当\(a \in [1,l - 1],b \in [l,r]\)时,此时有\(\frac{1}{len}\)的概率改变不等关系

当\(a \in [l,r],b \in [r + 1,n]\)时,此时有\(\frac{1}{len}\)的概率改变不等关系

当\(a,b \in [l,r]\)时,此时有\(\frac{2}{len}\)的概率改变不等关系

所以我们可以使用二维线段树维护这些区域的概率值

如果原不等概率为\(p_0\),现在有\(p_1\)的概率改变不等关系

那么新的概率\(p' = p_0(1 - p_1) + (1 - p_0)p_1 = p_0 + p_1 - 2p_0p_1\)

我们记其为概率的合并

经计算可以得出,这样的合并满足交换律结合律单位元是\(0\)

所以我们可以使用线段树很方便地维护

同时为了简化操作,我们采用标记永久化

现在就可以理解我们为什么要维护不等概率了,因为初值为\(0\),恰好也为合并运算的单位元

二维线段树标记永久化的姿势:

内层线段树将标记储存在路径上的节点中

外层线段树则通过在修改中途访问内层线段树而就此停止,在询问时询问路径上所有的内层线段树即可

还要注意空间大小,\(O(nlog^2n)\)要开足够大的空间

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #include<map>
  7. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  8. #define REP(i,n) for (int i = 1; i <= (n); i++)
  9. #define mp(a,b) make_pair<int,int>(a,b)
  10. #define cls(s) memset(s,0,sizeof(s))
  11. #define cp pair<int,int>
  12. #define LL long long int
  13. using namespace std;
  14. const int maxn = 500005,maxm = 40000005,INF = 1000000000,P = 998244353;
  15. inline int read(){
  16. int out = 0,flag = 1; char c = getchar();
  17. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  18. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  19. return out * flag;
  20. }
  21. int qpow(int a,int b){
  22. int re = 1;
  23. for (; b; b >>= 1,a = 1ll * a * a % P)
  24. if (b & 1) re = 1ll * re * a % P;
  25. return re;
  26. }
  27. int inv(int x){return qpow(x,P - 2);}
  28. int merge(int x,int y){
  29. return (((x + y) % P - 2ll * x * y % P) + P) % P;
  30. }
  31. int n,m,ls[maxm],rs[maxm],val[maxm],rt[maxn << 2],cnt,ans;
  32. void modify(int& u,int l,int r,int L,int R,int v){
  33. if (!u) u = ++cnt;
  34. if (l >= L && r <= R){
  35. val[u] = merge(val[u],v);
  36. return;
  37. }
  38. int mid = l + r >> 1;
  39. if (mid >= L) modify(ls[u],l,mid,L,R,v);
  40. if (mid < R) modify(rs[u],mid + 1,r,L,R,v);
  41. }
  42. void query(int u,int l,int r,int pos){
  43. if (!u) return; ans = merge(ans,val[u]);
  44. if (l == r) return;
  45. int mid = l + r >> 1;
  46. if (mid >= pos) query(ls[u],l,mid,pos);
  47. else query(rs[u],mid + 1,r,pos);
  48. }
  49. void Modify(int u,int l,int r,int L,int R,int ll,int rr,int v){
  50. if (l >= L && r <= R){
  51. modify(rt[u],1,n,ll,rr,v);
  52. return;
  53. }
  54. int mid = l + r >> 1;
  55. if (mid >= L) Modify(u << 1,l,mid,L,R,ll,rr,v);
  56. if (mid < R) Modify(u << 1 | 1,mid + 1,r,L,R,ll,rr,v);
  57. }
  58. void Query(int u,int l,int r,int Pos,int pos){
  59. if (rt[u]) query(rt[u],1,n,pos);
  60. if (l == r) return;
  61. int mid = l + r >> 1;
  62. if (mid >= Pos) Query(u << 1,l,mid,Pos,pos);
  63. else Query(u << 1 | 1,mid + 1,r,Pos,pos);
  64. }
  65. int main(){
  66. //freopen("in.in","r",stdin);
  67. //freopen("out1.txt","w",stdout);
  68. n = read(); m = read();
  69. int opt,l,r,len,p;
  70. while (m--){
  71. opt = read(); l = read(); r = read();
  72. if (opt & 1){
  73. len = r - l + 1; p = inv(len);
  74. if (l > 1){
  75. Modify(1,1,n,1,l - 1,l,r,p);
  76. modify(rt[0],1,n,1,l - 1,1);
  77. }
  78. if (r < n){
  79. Modify(1,1,n,l,r,r + 1,n,p);
  80. modify(rt[0],1,n,r + 1,n,1);
  81. }
  82. Modify(1,1,n,l,r,l,r,2 * p % P);
  83. modify(rt[0],1,n,l,r,(1 - p + P) % P);
  84. }
  85. else {
  86. ans = 0;
  87. if (l > 1) Query(1,1,n,l - 1,r);
  88. else query(rt[0],1,n,r);
  89. printf("%d\n",(1 - ans + P) % P);
  90. }
  91. }
  92. return 0;
  93. }

BZOJ4785 [Zjoi2017]树状数组 【二维线段树 + 标记永久化】的更多相关文章

  1. bzoj4785:[ZJOI2017]树状数组:二维线段树

    分析: "如果你对树状数组比较熟悉,不难发现可怜求的是后缀和" 设数列为\(A\),那么可怜求的就是\(A_{l-1}\)到\(A_{r-1}\)的和(即\(l-1\)的后缀减\( ...

  2. BZOJ 4785 [Zjoi2017]树状数组 | 二维线段树

    题目链接 BZOJ 4785 题解 这道题真是令人头秃 = = 可以看出题面中的九条可怜把求前缀和写成了求后缀和,然后他求的区间和却仍然是sum[r] ^ sum[l - 1],实际上求的是闭区间[l ...

  3. BZOJ4822[Cqoi2017]老C的任务——树状数组(二维数点)

    题目描述 老 C 是个程序员.     最近老 C 从老板那里接到了一个任务——给城市中的手机基站写个管理系统.作为经验丰富的程序员,老 C 轻松 地完成了系统的大部分功能,并把其中一个功能交给你来实 ...

  4. BZOJ1935: [Shoi2007]Tree 园丁的烦恼(树状数组 二维数点)

    题意 题目链接 Sol 二维数点板子题 首先把询问拆成四个矩形 然后离散化+树状数组统计就可以了 // luogu-judger-enable-o2 #include<bits/stdc++.h ...

  5. 树状数组 二维偏序【洛谷P3431】 [POI2005]AUT-The Bus

    P3431 [POI2005]AUT-The Bus Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 ...

  6. 树状数组+二维前缀和(A.The beautiful values of the palace)--The Preliminary Contest for ICPC Asia Nanjing 2019

    题意: 给你螺旋型的矩阵,告诉你那几个点有值,问你某一个矩阵区间的和是多少. 思路: 以后记住:二维前缀和sort+树状数组就行了!!!. #define IOS ios_base::sync_wit ...

  7. bzoj 4822: [Cqoi2017]老C的任务【扫描线+树状数组+二维差分】

    一个树状数组能解决的问题分要用树套树--还写错了我别是个傻子吧? 这种题还是挺多的,大概就是把每个矩形询问差分拆成四个点前缀和相加的形式(x1-1,y1-1,1)(x2.y2,1)(x1-1,y2,- ...

  8. 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询

    Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  9. [Usaco2014 Open Gold ]Cow Optics (树状数组+扫描线/函数式线段树)

    这道题一上手就知道怎么做了= = 直接求出原光路和从目标点出发的光路,求这些光路的交点就行了 然后用树状数组+扫描线或函数式线段树就能过了= = 大量的离散+模拟+二分什么的特别恶心,考试的时候是想到 ...

  10. HDU - 1166 树状数组模板(线段树也写了一遍)

    题意: 汉语题就不说题意了,用到单点修改和区间查询(树状数组和线段树都可以) 思路: 树状数组的单点查询,单点修改和区间查询. 树状数组是巧妙运用二进制的规律建树,建树就相当于单点修改.这里面用到一个 ...

随机推荐

  1. 【转载】vue.js实现格式化时间并每秒更新显示功能示例

    引用:https://www.jb51.net/article/143351.htm 这篇文章主要介绍了vue.js实现格式化时间并每秒更新显示功能,结合实例形式分析了vue.js时间格式化显示与基于 ...

  2. php-语言参考-类型3.2-未完待续

    一,PHP变量的8个类型 四种标量类型: boolean (布尔型) integer (整型) float (浮点型, 也称作 double) string (字符串) 两种复合类型: array ( ...

  3. DJANGO2.0 关联表的必填 ON_DELETE

    DJANGO2.0 关联表的必填 ON_DELETE 参数的含义 - BUXIANGHEJIU 的博客 - CSDN 博客 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...

  4. oracle监听配置

    在listener.ora文件中指定监听的实例名和修改ip地址: 查看实例名:[localhost$] echo $ORACLE_SID LISTENER = (DESCRIPTION_LIST = ...

  5. Kubernetes-运维指南

    Node隔离与恢复 cat unschedule_node.yaml apiVersion: kind: Node metadata: name: k8s-node-1 labels: kuberne ...

  6. AtCoder AGC028-F:Reachable Cells

    越来越喜欢AtCoder了,遍地都是神仙题. 题意: 给定一个\(N\)行\(N\)列的迷宫,每一个格子要么是障碍,要么是空地.每一块空地写着一个数码.在迷宫中,每一步只允许向右.向下走,且只能经过空 ...

  7. Lambda表达式详解【转】

    前言 1.天真热,程序员活着不易,星期天,也要顶着火辣辣的太阳,总结这些东西. 2.夸夸lambda吧:简化了匿名委托的使用,让你让代码更加简洁,优雅.据说它是微软自c#1.0后新增的最重要的功能之一 ...

  8. 云计算之路-阿里云上:基于Xen的IO模型进一步分析“黑色0.1秒”问题

    在发现云服务器读取OCS缓存的“黑色0.1秒”是发生在socket读取数据时,而且是发生在读取开始的字节,甚至在socket写数据时(比如写入缓存key)也会出现超过50ms的情况,我们的好奇心被激发 ...

  9. K8s集群内热改代码

    1.登录到k8s master服务器 $ ssh developer@XXX.XXX.X.XXX(IP地址) 2.查看服务容器所在的节点(以xx-server为例) $ kubectl get pod ...

  10. CSS3 :animation 动画

    CSS3动画分为二部份: 1.定义动画行为: 使用@keyframes定义动画行为,有两种方式: 方式一:仅定义动画起始样式,与动画结束样式 @keyframes (动画行为名称) { from {b ...