【BZOJ3821/UOJ46】玄学(二进制分组,线段树)

题面

BZOJ

UOJ

题解

呜,很好的题目啊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】玄学(二进制分组,线段树)的更多相关文章

  1. [BZOJ 2989]数列(二进制分组+主席树)

    [BZOJ 2989]数列(二进制分组+主席树) 题面 给定一个长度为n的正整数数列a[i]. 定义2个位置的graze值为两者位置差与数值差的和,即graze(x,y)=|x-y|+|a[x]-a[ ...

  2. 【BZOJ5294】[BJOI2018]二进制(线段树)

    [BZOJ5294][BJOI2018]二进制(线段树) 题面 BZOJ 洛谷 题解 二进制串在模\(3\)意义下,每一位代表的余数显然是\(121212\)这样子交替出现的. 其实换种方法看,就是\ ...

  3. bzoj2989&&4170数列——二进制分组+主席树

    题意的转化挺巧妙的 可以联想到曼哈顿距离! 并且,所谓的修改还要查询历史版本,并且修改之间不动只算一次,不就是给平面上加一个点吗? 看成(x,a[x])的点 就是一个菱形区域 转切比雪夫距离,变成矩形 ...

  4. UOJ46 【清华集训2014】玄学 【时间线段树】

    题目链接:UOJ 这题的时间线段树非常的妙. 对时间建立线段树,修改的时候在后面加,每当填满一个节点之后就合并进它的父亲. 对于一个节点维护序列,发现这是一个分段函数,合并就是归并排序.于是就形成了差 ...

  5. 2019.02.12 bzoj5294: [Bjoi2018]二进制(线段树)

    传送门 题意简述: 给出一个长度为nnn的二进制串. 你需要支持如下操作: 修改每个位置:1变0,0变1 询问对于一个区间的子二进制串有多少满足重排之后转回十进制值为333的倍数(允许前导000). ...

  6. 2019.01.21 bzoj2989: 数列(二进制分组+主席树)

    传送门 二进制分组入门题. 主席树写错调题2h+2h+2h+体验极差. 题意简述:给一堆点,支持加入一个点,询问有多少个点跟(x,y)(x,y)(x,y)曼哈顿距离不超过kkk. 思路:题目要求的是对 ...

  7. Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))

    题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一 ...

  8. 洛谷P4428二进制 [BJOI2018] 线段树

    正解:线段树 解题报告: 传送门! 话说开始看到这题的时候我想得hin简单 因为关于%3有个性质就是说一个数的各个位数之和%3=这个数%3嘛,小学基础知识? 我就想着,就直接建一棵树,只是这棵树要用个 ...

  9. BZOJ5294 [BJOI2018] 二进制 【线段树】

    BJOI的题目感觉有点难写 题目分析: 首先推一波结论.接下来的一切都在模3意义下 现在我们将二进制位重组,不难发现的是2^0≡1,2^1≡2,2^2≡1,2^3≡2....所以我们考虑这样的式子 2 ...

  10. BZOJ5294 BJOI2018二进制(线段树)

    二进制数能被3整除相当于奇数.偶数位上1的个数模3同余.那么如果有偶数个1,一定存在重排方案使其合法:否则则要求至少有两个0且至少有3个1,这样可以给奇数位单独安排3个1. 考虑线段树维护区间内的一堆 ...

随机推荐

  1. 【php增删改查实例】第十四节 - 用户管理模块(起步)

    从这一节开始,开始着手开发部门管理模块. 之后的内容就在此基础上进行增加. 1.用户查询 在目录中建立一个user文件夹,作为我们用户管理的模块. 打开这个文件,新建一个userManage.html ...

  2. 全自动数据表格JQuery版

    由于最近工作上有些变动,已经快一个月没有写博客了.上一篇博客[React]全自动数据表格组件——BodeGrid介绍了全自动数据表格的设计思路以及分享了一个react.js的实现.但是现实情况中为了节 ...

  3. 【变态需求】bootstrapTable列排序-选择正序倒序不排序

    产品经理:那个table排序能不能点击后弹个选项选择正序倒序不排序? -- 那个是bootstrapTable的插件!不支持!改不了!! 注意:数据上假的,效果看http请求参数进行脑补 这是boot ...

  4. 自动化批量管理工具salt-ssh - 运维小结

    根据以往运维工作中操作经验来说,当管理上百台上千台服务器时,选择一款批量操作工具是及其有必要的.早期习惯于在ssh信任关系的前提下做for;do;done循环语句的批量操作,后来逐渐趋于使用批量工具操 ...

  5. taro之React Native 端开发研究

    初步结论:如果想把 React Native 集成到现有的原生项目中,不能使用taro的React Native 端开发功能(目前来说不能实现,以后再观察).   RN开发有2种模式: 1.一是原生A ...

  6. 牛客多校第二场A run(基础DP)

    链接:https://www.nowcoder.com/acm/contest/140/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言2621 ...

  7. 软件工程附加篇章:进阶四则运算和Core对接

    0x01 :计算模块(Core)和前端对接 首先特别结对编程刘乾组(SivilTaram)提供的计算模块(Core),http://www.cnblogs.com/SivilTaram/p/48599 ...

  8. 《Linux内核设计与实现》读书笔记 1&2

    第一章    Linux内核简介 1.2追寻Linus足迹:linux简介 Linus开发.Linux是类Unix系统.Linux内核也是自由软件. 1.3操作系统和内核简介 操作系统:在整个系统中负 ...

  9. [日常工作] SUSE设置上网ip地址

    1. 同事搜到的命令 ifconfig eth0 10.24.25.8 netmask 255.255.0.0 up route add default gw 10.24.255.254 2. 修改 ...

  10. msql 复杂练习

    https://blog.csdn.net/xiao__oaix/article/details/78122294 customer表branch 表account 表 depositor 表loan ...