【BZOJ3821/UOJ46】玄学(二进制分组,线段树)
【BZOJ3821/UOJ46】玄学(二进制分组,线段树)
题面
题解
呜,很好的题目啊QwQ。
离线做法大概可以线段树分治,或者直接点记录左右两次操作时的结果,两个除一下就可以直接计算。
强制在线的话,一般而言,分治在线就弄成二进制分组。把所有修改操作进行二进制分组,每次新加入一个修改操作的时候考虑和前面其他的操作合并,提前构出来线段树,按照次序插入。如果一个节点的左右儿子都填满了修改操作的话,那么把它的两个儿子的值进行合并。然而我们发现并不可能每个节点维护一棵线段树来表示所有的位置的值,实际上,因为每次修改影响的都是一段区间,所以可以用\(vector\)记录修改区间,每次只需要把左右儿子的所有断点合并起来分段就好了,这样子每个修改操作每次贡献\(1\)个断点,所以在整个线段树上最多贡献\(log\)个断点,直接暴力合并就可以了。
这样子每次查询就可以直接在线段树上查询啦。
似乎说的不清楚,看看代码就懂了
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
#define lson (now<<1)
#define rson (now<<1|1)
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int type,n,Q,tot,m,lans,a[MAX];
struct Node{int l,r,a,b;}t[MAX<<2];
void calc(int &a,int &b,int x,int y){a=1ll*a*x%m;b=(1ll*b*x+y)%m;}
Node operator+(Node a,Node b){calc(a.a,a.b,b.a,b.b);return a;}
vector<Node> s[MAX<<2];
void Build(int now,int l,int r)
{
s[now].push_back((Node){1,n,1,0});
if(l==r)return;int mid=(l+r)>>1;
Build(lson,l,mid);Build(rson,mid+1,r);
}
void pushup(int now)
{
s[now].clear();
int l1=s[lson].size(),l2=s[rson].size();
for(int i=0,j=0,l=0;i<l1&&j<l2;)
{
int a=s[lson][i].a,b=s[lson][i].b;
calc(a,b,s[rson][j].a,s[rson][j].b);
if(s[lson][i].r<=s[rson][j].r)
{
s[now].push_back((Node){l+1,s[lson][i].r,a,b});
l=s[lson][i].r;
if(s[lson][i].r==s[rson][j].r)++i,++j;
else ++i;
}
else
{
s[now].push_back((Node){l+1,s[rson][j].r,a,b});
l=s[rson][j].r;++j;
}
}
return;
}
bool Modify(int now,int l,int r,int p,Node a)
{
if(l==r)
{
if(a.l!=1)s[now].push_back((Node){1,a.l-1,1,0});
s[now].push_back(a);
if(a.r!=n)s[now].push_back((Node){a.r+1,n,1,0});
return true;
}
int mid=(l+r)>>1;
if(p<=mid){Modify(lson,l,mid,p,a);return false;}
else
{
bool fl=Modify(rson,mid+1,r,p,a);
if(fl)pushup(now);
return true;
}
}
Node Query(int now,int l,int r,int L,int R,int k)
{
if(L==l&&r==R)
{
int l=0,r=s[now].size();
while(l<=r)
{
int mid=(l+r)>>1;
if(s[now][mid].l<=k&&k<=s[now][mid].r)return s[now][mid];
if(s[now][mid].r<k)l=mid+1;
else r=mid-1;
}
}
int mid=(l+r)>>1;
if(R<=mid)return Query(lson,l,mid,L,R,k);
if(L>mid)return Query(rson,mid+1,r,L,R,k);
return Query(lson,l,mid,L,mid,k)+Query(rson,mid+1,r,mid+1,R,k);
}
int main()
{
type=read();
n=read();m=read();
for(int i=1;i<=n;++i)a[i]=read();
Q=read();
while(Q--)
{
int opt=read(),l=read(),r=read();
if(type&1)l^=lans,r^=lans;
if(opt==1)
{
int a=read(),b=read();++tot;
Modify(1,1,100000,tot,(Node){l,r,a,b});
}
else
{
int x=read();if(type&1)x^=lans;
Node u=Query(1,1,100000,l,r,x);
lans=(1ll*u.a*a[x]+u.b)%m;
printf("%d\n",lans);
}
}
return 0;
}
【BZOJ3821/UOJ46】玄学(二进制分组,线段树)的更多相关文章
- [BZOJ 2989]数列(二进制分组+主席树)
[BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...
- 【BZOJ5294】[BJOI2018]二进制(线段树)
[BZOJ5294][BJOI2018]二进制(线段树) 题面 BZOJ 洛谷 题解 二进制串在模\(3\)意义下,每一位代表的余数显然是\(121212\)这样子交替出现的. 其实换种方法看,就是\ ...
- bzoj2989&&4170数列——二进制分组+主席树
题意的转化挺巧妙的 可以联想到曼哈顿距离! 并且,所谓的修改还要查询历史版本,并且修改之间不动只算一次,不就是给平面上加一个点吗? 看成(x,a[x])的点 就是一个菱形区域 转切比雪夫距离,变成矩形 ...
- UOJ46 【清华集训2014】玄学 【时间线段树】
题目链接:UOJ 这题的时间线段树非常的妙. 对时间建立线段树,修改的时候在后面加,每当填满一个节点之后就合并进它的父亲. 对于一个节点维护序列,发现这是一个分段函数,合并就是归并排序.于是就形成了差 ...
- 2019.02.12 bzoj5294: [Bjoi2018]二进制(线段树)
传送门 题意简述: 给出一个长度为nnn的二进制串. 你需要支持如下操作: 修改每个位置:1变0,0变1 询问对于一个区间的子二进制串有多少满足重排之后转回十进制值为333的倍数(允许前导000). ...
- 2019.01.21 bzoj2989: 数列(二进制分组+主席树)
传送门 二进制分组入门题. 主席树写错调题2h+2h+2h+体验极差. 题意简述:给一堆点,支持加入一个点,询问有多少个点跟(x,y)(x,y)(x,y)曼哈顿距离不超过kkk. 思路:题目要求的是对 ...
- Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))
题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...
- 洛谷P4428二进制 [BJOI2018] 线段树
正解:线段树 解题报告: 传送门! 话说开始看到这题的时候我想得hin简单 因为关于%3有个性质就是说一个数的各个位数之和%3=这个数%3嘛,小学基础知识? 我就想着,就直接建一棵树,只是这棵树要用个 ...
- BZOJ5294 [BJOI2018] 二进制 【线段树】
BJOI的题目感觉有点难写 题目分析: 首先推一波结论.接下来的一切都在模3意义下 现在我们将二进制位重组,不难发现的是2^0≡1,2^1≡2,2^2≡1,2^3≡2....所以我们考虑这样的式子 2 ...
- BZOJ5294 BJOI2018二进制(线段树)
二进制数能被3整除相当于奇数.偶数位上1的个数模3同余.那么如果有偶数个1,一定存在重排方案使其合法:否则则要求至少有两个0且至少有3个1,这样可以给奇数位单独安排3个1. 考虑线段树维护区间内的一堆 ...
随机推荐
- 省市区三级联动,JS实现
文件下载地址:http://files.cnblogs.com/files/chenwolong/jsAddress.rar 示例截图: 在这里自己记录一个方法: function cmbAddOpt ...
- C#_委托的使用
C#基础---委托的使用 一:什么是委托 委托是一种定义方法签名的类型当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联.您可以通过委托实例调用方法.委托是一个引用类型,所以它具 ...
- nginx反向代理中proxy_set_header 运维笔记
Nginx proxy_set_header:即允许重新定义或添加字段传递给代理服务器的请求头.该值可以包含文本.变量和它们的组合.在没有定义proxy_set_header时会继承之前定义的值.默认 ...
- mysql操作命令梳理(1)-索引
1.创建索引索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.以下命令语句分别展示了如何创建主键索引(PRIMARY KE ...
- 最好使用%f输出浮点数据,acm
今天做题的时候发现使用%lf输出的时候总是wrong,而一旦改成%f就ac了,询问学长后知道,不要用%lf输出,浮点都用%f 然而我还是有疑惑,如果%f容不下输出的数据怎么办呢? 于是我就去百度 原来 ...
- 安装Visual Studio2013
安装Visual Studio2013现在官网下载在选择安装的可选功能这里,大家可以根据自己需要勾选,也可以默认全选.这里有个小功能,把鼠标放在文字上,会弹出各个功能的详细描述.选择四个常用的功能,另 ...
- 个人作业Week3
个人作业week3 一. 调研,评测 1.我的使用体验 版本:IOS版 BUG_1: 点击单词本中的“同步”后,会提示登录Microsoft账户.登录成功立即开始同步单词本.在单词本同步过程中, ...
- Week 3 有求必应
[引] 必应词典已经伴我很久了,但那并不意味着我天天都用它查来查去,它总是静静地蹲在我E盘的一角. 从前的它特别任性,总喜欢开机自己冒出头来看我.后来我嫌它每天都播报新闻,于是就把它关进了冷宫.直到不 ...
- BUAAMOOC项目M2 postmortem
设想和目标 1.我们的软件要解决什么问题?是否定义的很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件是基于北航MOOC网站做的Android手机客户端,用于便捷的在学校里通过手机做到随时随地 ...
- Linux内核分析作业第四周
系统调用的三个层次 一.用户态.内核态和中断 用户通过库函数与系统调用联系起来. 1.内核态 在高的执行级别下,代码可以执行特权指令,访问任意的物理地址,这时的CPU就对应内核态 2.用户态: 在低级 ...