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

转载于:https://www.cnblogs.com/cjyyb/p/10087923.html

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

  1. bzoj29894170数列——二进制分组+主席树

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

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

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

  3. 皮卡丘的梦想2(线段树+二进制状态压缩)

    Description 一天,一只住在 501 实验室的皮卡丘决定发奋学习,成为像 LeiQ 一样的巨巨,于是他向镇上的贤者金桔请教如何才能进化成一只雷丘. 金桔告诉他需要进化石才能进化,并给了他一个 ...

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

    [描述] 巨酱有n副耳机,他把它们摆成了一列,并且由1到n依次编号.每个耳机有一个玄学值,反映了各自的一些不可名状的独特性能.玄学值都是0到m−1间的整数.在外界的作用下(包括但不限于换线.上放.更换 ...

  5. 中国石油大学(华东)暑期集训--二进制(BZOJ5294)【线段树】

    问题 C: 二进制 时间限制: 1 Sec  内存限制: 128 MB 提交: 8  解决: 2 [提交] [状态] [讨论版] [命题人:] 题目描述 pupil发现对于一个十进制数,无论怎么将其的 ...

  6. Codeforces Round #807 (Div. 2) E. Mark and Professor Koro 二进制/线段树

    题目分析 模拟题目不难发现,实际上擦除操作就是在模拟二进制加法进位.那么可以得到原题意的转述: 将每个 a [ i ] a[i] a[i]看作 2 a [ i ] 2^{a[i]} 2a[i],维护整 ...

  7. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  8. YbtOJ#752-最优分组【笛卡尔树,线段树】

    正题 题目链接:http://www.ybtoj.com.cn/problem/752 题目大意 nnn个人,每个人有cic_ici​和did_idi​分别表示这个人所在的队伍的最少/最多人数. 然后 ...

  9. 【线段树】二进制(luogu 4428)

    正题 luogu 4428 题目大意 给你一个01串,让你进行一下两种操作: 1.将其中一位取反 2.问你某一段中有多少个子串满足有一种排列方案,使得组成的二进制数是3的倍数 解题思路 不难发现,因为 ...

最新文章

  1. Linux_学习_01_常用命令大全
  2. Android开发四年以来的工作难点总结
  3. Spring5源码 - 09 循环依赖解读
  4. android init.rc中启动的service 默认是disable的,后续如何启动此服务
  5. 大数据场景中语言虚拟机的应用和挑战
  6. 【法克鱿】域名DNS设置修改失败!
  7. The NVIDIA driver on your system is too old (found version 10000). Please update your GPU driver by
  8. canal DevGuide
  9. Leetcode每日一题:189.rotate-array(旋转数组)
  10. Docker动荡在继续:创始人兼CTO离职
  11. Asp.Net超时问题汇总
  12. 【java】变量的应用
  13. Android IPC(二)Messenger实现跨进程双向通信
  14. [人工智能-深度学习-58]:生成对抗网络GAN - 概述与常见应用
  15. C2P工业云进销存管理有什么优势?
  16. 三色SM认证人脸动态视频制作教程
  17. 计算机木材染色 配色技术的应用技术,计算机配色技术在木材连缸染色中的应用研究.pdf...
  18. fan4801开关电源原理图_全面解析开关电源各功能电路(附原理图)
  19. Linux命令 - wget
  20. android手机舆情分析,基于Android平台的环境公共舆情监督系统研究

热门文章

  1. ExpressQuantumGrid.Suite.v6.30 在Delphi 7中的安装 收藏
  2. Linux没有安装gcc如何在线安装(直接在Linux终端安装)
  3. 程序员面试系列——合并排序(递归实现)
  4. Jackson 注解 -- 忽略字段
  5. Lock接口Condition,以及Lock与synchronized异同
  6. LIVE555再学习 -- DM368/Hi3516A 交叉编译
  7. phpcms 指定id范围 调用_phpcms v9使用GET调用指定id文章内容、页面数据方法
  8. 【译】Everything You Need to Know About Decentralized AI
  9. 深入理解 Java 锁与线程阻塞
  10. 【译】What do machine learning practitioners actually do?