题链:

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]树状数组的更多相关文章

  1. 洛谷 P3688 - [ZJOI2017]树状数组(二维线段树+标记永久化)

    题面传送门 首先学过树状数组的应该都知道,将树状数组方向写反等价于前缀和 \(\to\) 后缀和,因此题目中伪代码的区间求和实质上是 \(sum[l-1...n]-sum[r...n]=sum[l-1 ...

  2. P3688 [ZJOI2017] 树状数组 【二维线段树】

    题目描述:这里有一个写挂的树状数组: 有两种共\(m\)个操作: 输入\(l,r\),在\([l,r]\)中随机选择一个整数\(x\)执行\(\text{Add}(x)\) 输入\(l,r\),询问执 ...

  3. 洛谷.3374.[模板]树状数组1(CDQ分治)

    题目链接 简易CDQ分治教程 //每个操作分解为一个有序数对(t,p),即(时间,操作位置),时间默认有序,用CDQ分治处理第二维 //对于位置相同的操作 修改优先于查询 //时间是默认有序的 所以可 ...

  4. [BZOJ4785][ZJOI2017]树状数组(概率+二维线段树)

    4785: [Zjoi2017]树状数组 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 297  Solved: 195[Submit][Status ...

  5. 【BZOJ4785】[Zjoi2017]树状数组 树套树(二维线段树)

    [BZOJ4785][Zjoi2017]树状数组 Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一 ...

  6. 洛谷P3688/uoj#291. [ZJOI2017]树状数组

    传送门(uoj) 传送门(洛谷) 这里是题解以及我的卡常数历程 话说后面那几组数据莫不是lxl出的这么毒 首先不难发现这个东西把查询前缀和变成了查询后缀和,结果就是查了\([l-1,r-1]\)的区间 ...

  7. bzoj4785 [Zjoi2017]树状数组

    Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进 ...

  8. [ZJOI2017]树状数组

    Description 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道 基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来 ...

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

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

随机推荐

  1. beta冲刺2-咸鱼

    q前言:今天晚上大概把github的的相关东西弄上了.然后把之前做的一些修改什么的也上传上去了.目测之后的话就是在自己这边改完然后直接上github那边去复制粘贴替换掉了. 昨天的问题:github这 ...

  2. selenium webdriver API

    元素定位 #coding=utf-8 from selenium import webdriver from selenium.webdriver.firefox.firefox_binary imp ...

  3. 源端控制的OpenFlow数据面

    OpenFlow 交换机一般采用 TCAM 存储和查找流表,从而带来了扩展性.成本和能耗的问题.TCAM 成本和能耗过高,存储容量有限,一般交换机中的 TCAM 仅能存储几千条流表项,对 OpenFl ...

  4. 项目Beta冲刺Day6

    项目进展 李明皇 今天解决的进度 进行前后端联动调试 明天安排 完善程序运行逻辑 林翔 今天解决的进度 服务器端发布消息,删除消息,检索消息,个人发布的action 明天安排 图片功能遇到问题,微信小 ...

  5. Beta集合

    Beta冲刺day1 Beta冲刺day2 Beta冲刺day3 Beta冲刺day4 Beta冲刺day5 Beta冲刺day6 Beta冲刺day7 测试总结 总结合集 Beta预备

  6. LeetCode & Q26-Remove Duplicates from Sorted Array-Easy

    Descriptions: Given a sorted array, remove the duplicates in place such that each element appear onl ...

  7. SpringCloud的Hystrix(五) Hystrix机制

    参考链接:http://www.jianshu.com/p/e07661b9bae8 一.前言 大型复杂的分布式系统中,高可用相关的技术架构非常重要.高可用架构非常重要的一个环节,就是如何将分布式系统 ...

  8. SpringCloud的注解:汇总篇

    使用注解之前要开启自动扫描功能,如下配置中base-package为需要扫描的包(含子包): 1 <context:component-scan base-package="cn.te ...

  9. 面向对象的PHP(5)

    OOP的好处 封装 封装可以隐藏实现细节,使代码模块化,代码重用 继承 继承可以扩展已存在的代码模块(class),代码重用 多态 为了类在继承和派生的时候,保证实例的某一属性正确调用,接口重用 关键 ...

  10. jquery-模仿qq提示消息

    ( function() { var ua = navigator.userAgent.toLowerCase(); var is = (ua.match(/\b(chrome|opera|safar ...