题目链接

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)\)要开足够大的空间

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 500005,maxm = 40000005,INF = 1000000000,P = 998244353;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int qpow(int a,int b){
int re = 1;
for (; b; b >>= 1,a = 1ll * a * a % P)
if (b & 1) re = 1ll * re * a % P;
return re;
}
int inv(int x){return qpow(x,P - 2);}
int merge(int x,int y){
return (((x + y) % P - 2ll * x * y % P) + P) % P;
}
int n,m,ls[maxm],rs[maxm],val[maxm],rt[maxn << 2],cnt,ans;
void modify(int& u,int l,int r,int L,int R,int v){
if (!u) u = ++cnt;
if (l >= L && r <= R){
val[u] = merge(val[u],v);
return;
}
int mid = l + r >> 1;
if (mid >= L) modify(ls[u],l,mid,L,R,v);
if (mid < R) modify(rs[u],mid + 1,r,L,R,v);
}
void query(int u,int l,int r,int pos){
if (!u) return; ans = merge(ans,val[u]);
if (l == r) return;
int mid = l + r >> 1;
if (mid >= pos) query(ls[u],l,mid,pos);
else query(rs[u],mid + 1,r,pos);
}
void Modify(int u,int l,int r,int L,int R,int ll,int rr,int v){
if (l >= L && r <= R){
modify(rt[u],1,n,ll,rr,v);
return;
}
int mid = l + r >> 1;
if (mid >= L) Modify(u << 1,l,mid,L,R,ll,rr,v);
if (mid < R) Modify(u << 1 | 1,mid + 1,r,L,R,ll,rr,v);
}
void Query(int u,int l,int r,int Pos,int pos){
if (rt[u]) query(rt[u],1,n,pos);
if (l == r) return;
int mid = l + r >> 1;
if (mid >= Pos) Query(u << 1,l,mid,Pos,pos);
else Query(u << 1 | 1,mid + 1,r,Pos,pos);
}
int main(){
//freopen("in.in","r",stdin);
//freopen("out1.txt","w",stdout);
n = read(); m = read();
int opt,l,r,len,p;
while (m--){
opt = read(); l = read(); r = read();
if (opt & 1){
len = r - l + 1; p = inv(len);
if (l > 1){
Modify(1,1,n,1,l - 1,l,r,p);
modify(rt[0],1,n,1,l - 1,1);
}
if (r < n){
Modify(1,1,n,l,r,r + 1,n,p);
modify(rt[0],1,n,r + 1,n,1);
}
Modify(1,1,n,l,r,l,r,2 * p % P);
modify(rt[0],1,n,l,r,(1 - p + P) % P);
}
else {
ans = 0;
if (l > 1) Query(1,1,n,l - 1,r);
else query(rt[0],1,n,r);
printf("%d\n",(1 - ans + P) % P);
}
}
return 0;
}

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. PyCharm+QT Designer整合

    CMD下使用pip安装PyQt4或者PYQT5 这里要注意,你下载的PYQT5不包含QT designer 还要:pip3 install PyQt5-tools,好像Pyqt5中将designer分 ...

  2. scala成长之路(2)对象和类

    scala提供了一种特殊的定义单例的方法:object关键字 scala> object Shabi{ | val age = 0 | val name = "shabi" ...

  3. Learning Experience of Big Data: Learn to install CentOs 6.5 on my laptop

    I have learnt some experience about Big Data during my summer vocation,I was told that The first thi ...

  4. http一些常见知识记录

    HTTP请求包(浏览器信息) 我们先来看看Request包的结构, Request包分为3部分,第一部分叫Request line(请求行), 第二部分叫Request header(请求头),第三部 ...

  5. mongodb常用命令学习笔记

    mongodb常用命令学习笔记 创建数据库 use DATABASE_NAME eg: use users; 如果数据库不存在,则创建数据库,否则切换到指定数据库.要显示刚刚创建的数据库,需要向数据库 ...

  6. HDU暑假多校第八场G-Card Game

    一.题意 给出N个卡牌,卡牌的正反两面具有两个数字,取值范围为[1,2*n],给出若干个默认正面向上的卡牌,求最小反转多少张卡牌可以使得,每张卡牌朝上的面上都有一个不同的数字,同时满足最小反转次数的反 ...

  7. JVM内存管理机制和垃圾回收机制

    JVM内存管理机制和垃圾回收机制 JVM结构 图片描述: java源码编译成class文件 class文件通过类加载器加载到内存 其中方法区存放的是运行时的常量.静态变量.类信息等,被所有线程共享 堆 ...

  8. hdu畅通工程(并查集)

    Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道 ...

  9. 【转】已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭

    在运用Linq to sql 或者 linq to entity等相关linq技术进行数据库访问操作时,如果发生上述异常是因为是因为.NET內部是使用DataReader作数据存取,DataReade ...

  10. LeetCode:26. Remove Duplicates from Sorted Array(Easy)

    1. 原题链接 https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/ 2. 题目要求 给定一个已 ...