题链:

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;
}

  

转载于:https://www.cnblogs.com/zj75211/p/8541662.html

●洛谷P3688 [ZJOI2017]树状数组相关推荐

  1. 洛谷[P3374] [P3368]树状数组(线段树解法)

    最近学习了线段树,不会树状数组,用线段树舔着脸来做一下 P3374树状数组1https://www.luogu.com.cn/problem/P3374 ac代码 #include<bits/s ...

  2. 洛谷模板,树状数组二 差分

    题目链接:https://www.luogu.org/problemnew/show/P3368 先介绍下差分: 设数组a[]={1,6,8,5,10},那么差分数组b[]={1,5,2,-3,5} ...

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

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

  4. [ZJOI2017]树状数组

    以后写题前还是要冷静分析清楚再动手啊..... $ Think \ twice,code \ once$ 传送门:here 大致题意: 有一个写挂的树状数组,$ query$的是后缀和,$ query ...

  5. 模板三连击:树状数组+线段树+主席树

    没事儿干,复习模板...... 1.树状数组 本来不想写这个的,但是反正就几分钟就打完了,所以就写了,水AC数. 洛谷 P3374 [模板]树状数组 1 1 #include<cstdio> ...

  6. 树状数组入门——以洛谷3374为例

    树状数组入门 含义:顾名思义,用树状表示的数组 功能:是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log( ...

  7. 洛谷P3374 【模板】树状数组 1

    题目链接:[模板]树状数组 1 - 洛谷 模板题就不多说了 ac代码: #include <cstdio> #include <iostream> #include <a ...

  8. 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)

    洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...

  9. (树状数组+逆元)洛谷P5142 区间方差

    洛谷P5142 区间方差 (^ w ^) 题目背景 出题人并没有能力写有趣的题面-- 题目描述 对于一个长度为n的序列a1,a2,a3⋯ana_1,a_2,a_3\cdots a_na1​,a2​,a ...

最新文章

  1. [JS]题解 | #岛屿数量#
  2. 【Python 】单引号和双引号有什么区别?
  3. openerp学习笔记 domain 的应用
  4. ShellAPI 调用搜索引擎
  5. loadrunner vuser 限制修改
  6. android 截屏 分享,Android应用内截图分享的实现记录
  7. Java中String, StringBuilder和StringBuffer
  8. html loading 页面加载中(百分比)
  9. 云台测试软件,三轴云台校准工具
  10. Python实现泛微OA云桥未授权任意文件读取
  11. Tensorflow serving 学习(一)
  12. 怎么设置锤子手机显示无服务器,锤子手机远程协助怎么使用 锤子手机远程协助使用教程【详解】...
  13. 编译器整数除法的优化
  14. canvas图片转素描
  15. 【算法学习笔记六】递归之归纳法
  16. 程序员有话说 | 原来你是这样的程序员:麦霸、大厨、舞林高手……
  17. 【UV打印机】理光喷头组合说明(5H)
  18. Unity VideoPlayer组件在5.6版本的坑
  19. nginx负载均衡之加权轮询
  20. 软件工程实践总结——程序员的自我修养

热门文章

  1. 【原创】Cookie应用(二)
  2. Windows 7的CMD中 Telnet 无法执行的解决办法
  3. java将实体类转化为json_只有实践才能将知识转化为智慧
  4. 反arp攻击软件_谈谈电子欺骗中的ARP欺骗
  5. 翻转矩阵(数组右移问题)
  6. linux分区通俗讲解,linux硬盘分区基础及设备号的解释
  7. 用C语言编写万年历6,C语言编写万年历
  8. linux 文件拷贝并替换,Linux_cmd replace 文件替换使用说明,帮助信息: 复制代码 代码如 - phpStudy...
  9. 织梦生成html加速,加快DEDECMS静态html网页生成速度的方法
  10. pendo android,Pendo