●洛谷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;
}
转载于:https://www.cnblogs.com/zj75211/p/8541662.html
●洛谷P3688 [ZJOI2017]树状数组相关推荐
- 洛谷[P3374] [P3368]树状数组(线段树解法)
最近学习了线段树,不会树状数组,用线段树舔着脸来做一下 P3374树状数组1https://www.luogu.com.cn/problem/P3374 ac代码 #include<bits/s ...
- 洛谷模板,树状数组二 差分
题目链接:https://www.luogu.org/problemnew/show/P3368 先介绍下差分: 设数组a[]={1,6,8,5,10},那么差分数组b[]={1,5,2,-3,5} ...
- 洛谷P3688/uoj#291. [ZJOI2017]树状数组
传送门(uoj) 传送门(洛谷) 这里是题解以及我的卡常数历程 话说后面那几组数据莫不是lxl出的这么毒 首先不难发现这个东西把查询前缀和变成了查询后缀和,结果就是查了\([l-1,r-1]\)的区间 ...
- [ZJOI2017]树状数组
以后写题前还是要冷静分析清楚再动手啊..... $ Think \ twice,code \ once$ 传送门:here 大致题意: 有一个写挂的树状数组,$ query$的是后缀和,$ query ...
- 模板三连击:树状数组+线段树+主席树
没事儿干,复习模板...... 1.树状数组 本来不想写这个的,但是反正就几分钟就打完了,所以就写了,水AC数. 洛谷 P3374 [模板]树状数组 1 1 #include<cstdio> ...
- 树状数组入门——以洛谷3374为例
树状数组入门 含义:顾名思义,用树状表示的数组 功能:是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之和,但是每次只能修改一个元素的值:经过简单修改可以在log( ...
- 洛谷P3374 【模板】树状数组 1
题目链接:[模板]树状数组 1 - 洛谷 模板题就不多说了 ac代码: #include <cstdio> #include <iostream> #include <a ...
- 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)
洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...
- (树状数组+逆元)洛谷P5142 区间方差
洛谷P5142 区间方差 (^ w ^) 题目背景 出题人并没有能力写有趣的题面-- 题目描述 对于一个长度为n的序列a1,a2,a3⋯ana_1,a_2,a_3\cdots a_na1,a2,a ...
最新文章
- [JS]题解 | #岛屿数量#
- 【Python 】单引号和双引号有什么区别?
- openerp学习笔记 domain 的应用
- ShellAPI 调用搜索引擎
- loadrunner vuser 限制修改
- android 截屏 分享,Android应用内截图分享的实现记录
- Java中String, StringBuilder和StringBuffer
- html loading 页面加载中(百分比)
- 云台测试软件,三轴云台校准工具
- Python实现泛微OA云桥未授权任意文件读取
- Tensorflow serving 学习(一)
- 怎么设置锤子手机显示无服务器,锤子手机远程协助怎么使用 锤子手机远程协助使用教程【详解】...
- 编译器整数除法的优化
- canvas图片转素描
- 【算法学习笔记六】递归之归纳法
- 程序员有话说 | 原来你是这样的程序员:麦霸、大厨、舞林高手……
- 【UV打印机】理光喷头组合说明(5H)
- Unity VideoPlayer组件在5.6版本的坑
- nginx负载均衡之加权轮询
- 软件工程实践总结——程序员的自我修养
热门文章
- 【原创】Cookie应用(二)
- Windows 7的CMD中 Telnet 无法执行的解决办法
- java将实体类转化为json_只有实践才能将知识转化为智慧
- 反arp攻击软件_谈谈电子欺骗中的ARP欺骗
- 翻转矩阵(数组右移问题)
- linux分区通俗讲解,linux硬盘分区基础及设备号的解释
- 用C语言编写万年历6,C语言编写万年历
- linux 文件拷贝并替换,Linux_cmd replace 文件替换使用说明,帮助信息: 复制代码 代码如 - phpStudy...
- 织梦生成html加速,加快DEDECMS静态html网页生成速度的方法
- pendo android,Pendo