●洛谷P3688 [ZJOI2017]树状数组
题链:
https://www.luogu.org/problemnew/show/P3688
题解:
二维线段树。
先不看询问时l=1的特殊情况。
对于一个询问(l,r),如果要让错误的程序得到正确答案,
显然应该满足l-1位置的值=r位置的值(或者说两个位置的异或值为0)。
那么定义二元组函数f(x,y)表示x位置与y位置的异或值为0的概率。
如果可以维护出所有这样的二元组的函数值,
对于一个询问的话,就可以很方便的回答了。
现在看看,怎样维护这样的二元组的函数值。
假设现在给出了一个操作1:(L,R),(令prob=1/len)
那么显然,对于如下这些二元组:(0~L-1,L~R)和(L~R,R+1~N),
它们的函数值都会乘上(1-prob),因为有(1-prob)的概率无法使得其异或值改变。
再对于这些二元组(L~R,L~R),它们的函数值都会乘上(1-2*prob)。
把上面的二元组看出平面上的点,那么每个操作1就对应着改变平面上若干个矩形的值。
所以就直接使用二维线段树(树套树)去维护二维区间修改+单点查询。
至于询问中l=1的情况,如果要让错误程序得到正确答案,那么[1~r-1]这一段的异或和就应该等于[r+1~N]这一段的异或和。
这里有这么一种做法:
记录到当前询问位置,之前有了cnt个1操作。
然后二维线段树查询f(0,r)的得到prob,
由于0位置不可能被随机到1操作,
所以prob就表示r位置被之前的所有1操作弄成0的概率,(即有偶数个1操作随机到了r位置的概率)。
如果cnt为偶数,那么一定[1~r-1]这一段和[r+1~N]这一段被1操作随机到的奇偶性相同,
也就是说[1~r-1]这一段的异或和就应该等于[r+1~N]这一段的异或和,所以答案就是prob.
反之,如果cnt为奇数,(1-prob)表示r位置被之前的所有1操作弄成1的概率,(即有奇数个1操作随机到了r位置的概率)。
这样的话那么也一定[1~r-1]这一段和[r+1~N]这一段被1操作随机到的奇偶性相同,
也就是说[1~r-1]这一段的异或和就应该等于[r+1~N]这一段的异或和,所以答案就是(1-prob).
代码:
#include<bits/stdc++.h>
#define MAXN 100005
using namespace std;
const int MOD=998244353;
int N,M,cnt;
int merge(int p1,int p2){
return (1ll*p1*p2+1ll*(1-p1+MOD)*(1-p2+MOD))%MOD;
}
struct SGT2{
int size;
int ls[MAXN*200],rs[MAXN*200],p[MAXN*200];
void Modify(int &u,int l,int r,int yl,int yr,int prob){
if(!u) u=++size,p[u]=1;
if(yl<=l&&r<=yr) return (void)(p[u]=merge(p[u],prob));
int mid=(l+r)>>1;
if(yl<=mid) Modify(ls[u],l,mid,yl,yr,prob);
if(mid<yr) Modify(rs[u],mid+1,r,yl,yr,prob);
}
int Query(int u,int l,int r,int py){
if(!u) return 1;
int ret=merge(1,p[u]);
if(l==r) return ret;
int mid=(l+r)>>1;
if(py<=mid) ret=merge(ret,Query(ls[u],l,mid,py));
else ret=merge(ret,Query(rs[u],mid+1,r,py));
return ret;
}
}DTy;
struct SGT1{
int size,root;
int ls[MAXN*2],rs[MAXN*2],yroot[MAXN*2];
void Modify(int &u,int l,int r,int xl,int xr,int yl,int yr,int prob){
if(!u) u=++size;
if(xl<=l&&r<=xr) return DTy.Modify(yroot[u],0,N+1,yl,yr,prob);
int mid=(l+r)>>1;
if(xl<=mid) Modify(ls[u],l,mid,xl,xr,yl,yr,prob);
if(mid<xr) Modify(rs[u],mid+1,r,xl,xr,yl,yr,prob);
}
int Query(int u,int l,int r,int px,int py){
if(!u) return 1;
int ret=merge(1,DTy.Query(yroot[u],0,N+1,py));
if(l==r) return ret;
int mid=(l+r)>>1;
if(px<=mid) ret=merge(ret,Query(ls[u],l,mid,px,py));
else ret=merge(ret,Query(rs[u],mid+1,r,px,py));
return ret;
}
}DTx;
int fastpow(int a,int b){
int ret=1;
for(;b;a=1ll*a*a%MOD,b>>=1)
if(b&1) ret=1ll*ret*a%MOD;
return ret;
}
int main(){
//cout<<fastpow(3,MOD-2)<<endl;
scanf("%d%d",&N,&M);
int t,l,r,prob,ans;
for(int i=1;i<=M;i++){
scanf("%d%d%d",&t,&l,&r);
if(t==1){
cnt++;
prob=fastpow(r-l+1,MOD-2);
DTx.Modify(DTx.root,0,N+1,0,l-1,l,r,(1ll-prob+MOD)%MOD);
DTx.Modify(DTx.root,0,N+1,l,r,r+1,N+1,(1ll-prob+MOD)%MOD);
if(r-l+1>=2) DTx.Modify(DTx.root,0,N+1,l,r,l,r,(1ll-2ll*prob+2ll*MOD)%MOD);
}
else{
l--;
ans=DTx.Query(DTx.root,0,N+1,l,r);
if(l==0){
if((cnt&1)==0) printf("%d\n",ans);
else printf("%d\n",(1-ans+MOD)%MOD);
}
else printf("%d\n",ans);
}
}
return 0;
}
●洛谷P3688 [ZJOI2017]树状数组的更多相关文章
- 洛谷 P3688 - [ZJOI2017]树状数组(二维线段树+标记永久化)
题面传送门 首先学过树状数组的应该都知道,将树状数组方向写反等价于前缀和 \(\to\) 后缀和,因此题目中伪代码的区间求和实质上是 \(sum[l-1...n]-sum[r...n]=sum[l-1 ...
- P3688 [ZJOI2017] 树状数组 【二维线段树】
题目描述:这里有一个写挂的树状数组: 有两种共\(m\)个操作: 输入\(l,r\),在\([l,r]\)中随机选择一个整数\(x\)执行\(\text{Add}(x)\) 输入\(l,r\),询问执 ...
- 洛谷.3374.[模板]树状数组1(CDQ分治)
题目链接 简易CDQ分治教程 //每个操作分解为一个有序数对(t,p),即(时间,操作位置),时间默认有序,用CDQ分治处理第二维 //对于位置相同的操作 修改优先于查询 //时间是默认有序的 所以可 ...
- [BZOJ4785][ZJOI2017]树状数组(概率+二维线段树)
4785: [Zjoi2017]树状数组 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 297 Solved: 195[Submit][Status ...
- 【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)
[BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一 ...
- 洛谷P3688/uoj#291. [ZJOI2017]树状数组
传送门(uoj) 传送门(洛谷) 这里是题解以及我的卡常数历程 话说后面那几组数据莫不是lxl出的这么毒 首先不难发现这个东西把查询前缀和变成了查询后缀和,结果就是查了\([l-1,r-1]\)的区间 ...
- bzoj4785 [Zjoi2017]树状数组
Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进 ...
- [ZJOI2017]树状数组
Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道 基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来 ...
- bzoj4785:[ZJOI2017]树状数组:二维线段树
分析: "如果你对树状数组比较熟悉,不难发现可怜求的是后缀和" 设数列为\(A\),那么可怜求的就是\(A_{l-1}\)到\(A_{r-1}\)的和(即\(l-1\)的后缀减\( ...
随机推荐
- 基于Python的Web应用开发实践总结
基于Python的Web应用开发学习总结 项目地址 本次学习采用的是Flask框架.根据教程开发个人博客系统.博客界面如图所示. 整个学习过程收获很多,以下是学习总结. 1.virtualenv ...
- Mysql5.7.17中文乱码问题
写Java web调数据库,老是出现汉字乱码,一直没理睬,今天决定好好"整治"一下,却发现并没有那么简单.从网上找的方法,大部分都尝试了一遍都有一些问题. 有的改完了,数据库启动不 ...
- 20162302 实验一《Java开发环境的熟悉》实验报告
实 验 报 告 课程:程序设计与数据结构 姓名:杨京典 班级:1623 学号:20162302 实验名称:Java开发环境的熟悉 实验器材:装有Ubuntu的联想拯救者80RQ 实验目的与要求:1.使 ...
- 201621123040《Java程序设计》第5周学习总结
1.本周学习总结 1.1写出你认为本周学习中比较重要的知识点关键词 关键词:接口 Comparable Comparator 比较排序 1.2尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需 ...
- 使用Putty连接Amazon EC2 Instance
Amazon的EC2中,默认是不允许使用用户名和密码直接连接Instance的,而是通过AWS (Amazon Web Service)提供的证书.在第一次使用EC2的时候,AWS会要求你创建一个证书 ...
- Java ftp 上传文件和下载文件
今天同事问我一个ftp 上传文件和下载文件功能应该怎么做,当时有点懵逼,毕竟我也是第一次,然后装了个逼,在网上找了一段代码发给同事,叫他调试一下.结果悲剧了,运行不通过.(装逼失败) 我找的文章链接: ...
- 第八条:覆盖equals时请遵守通用约定
==是物理相等 equals是逻辑相等 因为每个类的实例对象本质上都是唯一的 ,利用物理相等(==)是指一个实例只能相等于它自己. 利用逻辑相等是(equals)指 一个实例是否和另一个实例的某些关键 ...
- 微信支付 chooseWXPay:fail
本来以为解决了微信支付get_brand_wcpay_request:faill这个问题后就万事大吉了,结果又迈入了另一个坑... 问题原因: 1.生成签名的时间戳参数名timestamp的s大小写问 ...
- Hyper-V虚拟机故障导致数据文件丢失的数据恢复全过程
简介: 由于MD3200存储中虚拟机的数据文件丢失,导致整个Hyper-V服务瘫痪,虚拟机无法使用,故障环境为Windows Server 2012服务器,系统中部署了Hyper-V虚拟机环境,虚拟机 ...
- linux系统增加开机启动服务/应用
操作 在/etc/init.d下新建示例脚本文件(customize.sh),该脚本会启动zookeeper服务.内容如下: #!/bin/sh /usr/local/zookeeper-/bin/z ...