G - Caesar Cipher Gym - 102798G

题意:

对于一个区间,有两种操作,一种是对区间每个数+1再mod65536,另一种则是判断两个区间的数是否相同

题解:

参考题解:
很明显线段树,但是判断两个区间的数是否相同用什么?我们可以用hash
用线段树维护hash,区间修改和查询,判断两端hash是否相同
单hash模板如下:

for (int i=1;i<=len;i++)ans=ans*base+(ull)s[i];

现在我们看hash如何与线段树操作配套使用:

  1. 区间合并(pushup),线段树的每个节点表示这一段的hash值,区间合并时,大区间的hash = 左区间hash与右区间hash合并,我们知道hash的相邻为是以base为倍数的,所以合并时左区间的hash要乘baselen(len表示右区间的长度)+右区间的hash
    Hash[rt] = (Hash[rt << 1] * poww[r - mid] + Hash[rt << 1 | 1])
    base的倍数我们提前预处理
    你可以理解成12和34拼接成四位数,要12*102+34=1234
  2. 区间更新,要将一段区间都+1,我们要先知道hash等于什么,hash= ∑i=0nai∗basei\sum_{i=0}^n a_i * base^i∑i=0n​ai​∗basei,n=区间长度-1,现在我们将a[i]+=1,那么hash比原本多了∑i=0nbasei\sum_{i=0}^n base^i∑i=0n​basei,这里我们用前缀和记录,可以用lazy维护
  3. 查询操作和第一个区间合并也是类似,不是两个hash简单的合并,而且左区间的 hash值要先乘上 base ^ len(len为右区间长度) 再加右区间。
  4. 最后还要对65536取模,我们每次更新后用线段树维护每个区间的最大值,如果左区间最大值大于65536,继续更新左区间,复杂度log(n)

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int mod = 65536;
const int mod1 = 1e9 + 7;
const int base = 31;
const int maxn = 2e6 + 7;
ll Hash[maxn],ma[maxn],lazy[maxn];
//ma数组用来判断是否超出mod
ll pre[maxn],poww[maxn];   // r 的幂次     前缀和
int a[maxn] ,n,q,x,y,op,L;
void pushup(int l , int r, int rt){int mid = (l + r) / 2;Hash[rt] = (Hash[rt << 1] * poww[r - mid] % mod1 + Hash[rt << 1 | 1]) % mod1;ma[rt] = max(ma[rt << 1] , ma[rt << 1 | 1]);
}
void pushdown(int l,int r,int rt){if(lazy[rt] == 0) return ;int  mid = (l + r) / 2;Hash[rt << 1] = (Hash[rt << 1] + lazy[rt] *  pre[mid - l] % mod1) % mod1;     //加上前缀和的 幂次Hash[rt << 1 | 1] = (Hash[rt << 1 | 1] + lazy[rt] * pre[r - mid - 1] % mod1) % mod1;ma[rt << 1] += lazy[rt];ma[rt << 1|1] += lazy[rt];lazy[rt<<1] += lazy[rt];lazy[rt<<1|1] += lazy[rt];lazy[rt] = 0;
}
void update(int L,int R,int l,int r,int rt){if(L <= l && R >= r){Hash[rt] = (Hash[rt] + pre[r - l]) % mod1;lazy[rt] ++;ma[rt] ++;return ;}pushdown(l , r, rt);int mid = (l + r) / 2;if(R > mid) update(L , R ,mid + 1 ,r ,rt << 1 | 1);if(L <= mid) update(L ,R ,l , mid , rt << 1);pushup(l ,r , rt);
}
void update_mod(int l,int r,int rt){  //考虑溢出if(ma[rt] < mod){                 //没有超过 mod的 直接退出return ;}if(l == r){ma[rt] -= mod;Hash[rt] -= mod;return ;}pushdown(l , r, rt);int mid = (l + r) / 2;if(ma[rt << 1] >= mod) update_mod( l , mid ,rt << 1);if(ma[rt << 1 | 1] >= mod) update_mod(mid + 1 , r, rt << 1 | 1);pushup(l , r, rt);}
ll query(int L,int R,int l,int r,int rt){ll s = 0;if(L <= l && R >= r){return Hash[rt];}pushdown(l , r, rt);int mid = (l + r) / 2;if(R > mid)  s = (s + query(L,R,mid + 1,r,rt<<1|1) ) % mod1;if(L <= mid) s = (s + poww[max(0,min(R , r)- mid)] * query(L,R,l,mid,rt<<1) % mod1) % mod1;return s;
}
void build(int l,int r ,int rt){if(l == r){Hash[rt] = a[l];ma[rt] = a[l];return ;}int mid = (l + r) / 2;build(l , mid ,rt << 1);build(mid + 1 , r,rt << 1 | 1);pushup(l,r, rt);
}
int main (){poww[0] = pre[0] = 1;for(int i = 1; i <= 5e5 ; i ++){poww[i] = poww[i-1] * base % mod1;}//poww[i]=base^i for(int i = 1; i <= 5e5 ; i ++){pre[i] =  (pre[i-1] + poww[i]) % mod1;}//pre[r-l]=Σ(l+1->r)base^iscanf("%d%d",&n,&q);for(int i = 1; i<= n; i ++){scanf("%d",&a[i]);}build(1 , n,1);while(q--){scanf("%d",&op);if(op == 1){scanf("%d%d",&x,&y);update(x,y,1,n,1);update_mod(1 , n , 1);}if(op == 2){scanf("%d%d%d",&x,&y,&L);ll h1 = query(x , x + L - 1 ,1 , n, 1);ll h2 = query(y , y + L - 1 ,1 , n, 1);if(h1 == h2 ) printf ("yes\n");else printf ("no\n");}}
}

G - Caesar Cipher Gym - 102798G相关推荐

  1. 【Gym 102222C --- Caesar Cipher】

    [Gym 102222C --- Caesar Cipher] 题目来源:点击进入[Gym 102222C - Caesar Cipher] Description In cryptography, ...

  2. How to encrypt and decrypt the Caesar Cipher with python(Ⅱ)

    上一篇文章中介绍了如何用python来解密凯撒密码,但是那是在已知密钥的情况下才可行的,大多数情况下我们是不知道加密所用的密钥,如果通过人力进行手工破解费时费力,而且极易可能出错,所以我们可以借助py ...

  3. C++使用Caesar Cipher将加密的文本解密恢复为纯文本的算法(附完整源码)

    C++使用Caesar Cipher将加密的文本解密恢复为纯文本的算法 C++使用Caesar Cipher将加密的文本解密恢复为纯文本的算法完整源码(定义,实现,main函数测试) C++使用Cae ...

  4. Caesar Cipher

    题目: In cryptography, a Caesar cipher, also known as the shift cipher, is one of the most straightfor ...

  5. Codeforces - 102222C - Caesar Cipher

    https://codeforc.es/gym/102222/my 好像在哪里见过这个东西?字符的左右移还是小心,注意在mod26范围内. #include<bits/stdc++.h> ...

  6. G - Halli Galli Gym - 102801G

    Now there are K people play Halli Galli game.They will play N turns in all,in the order of the first ...

  7. 凯撒加密Caesar cipher与古典密码

    凯撒加密的由来 凯撒加密正是凯撒大帝发明的,是一种古典的加密 凯撒率军征服高卢,袭击日耳曼和不列颠,古罗马开启了走出意大利,征服全欧洲的征程 仅用8年时间征服高卢后,凯撒率军越过卢比孔河,驱赶政敌,成 ...

  8. UVa12604 Caesar Cipher(kmp)

    枚举字符串w可偏移后的字符串w',计算其前缀函数,看加密串s中包含w'的个数,如果为1,说明是满足要求的. 代码参考: https://github.com/wuli2496/OJ/tree/mast ...

  9. 2020CCPC(威海) - Caesar Cipher(线段树+哈希)

    题目大意:给出一个长度为 n 的序列,接下来有 m 次操作,每次操作分为下列两种类型: 1 l r:区间 [ l , r ] 内的所有数都加 1 并对 65536 取模,也就是 i ∈ [ l , r ...

最新文章

  1. sersync 同步
  2. [Swift]在不依赖三方库的情况下如何异步下载和缓存图片?
  3. leetcode算法题--下降路径最小和
  4. update module
  5. gridview 导出到excel,repeater类似
  6. 图像处理傅里叶变换的理解及其matlab实现
  7. mysql 装载dump文件_mysql命令、mysqldump命令找不到解决
  8. php 瀑布流布局,CSS3实现瀑布流布局的方法
  9. java 内存管理_高性能Java代码之内存管理
  10. 诸如北京现代 只有四个轮子和一电瓶由中国制造(转自新华网)
  11. html搜索联系人,联系人列表.html
  12. 为什么周报如此重要?如何才能写好周报
  13. 这些免费版音视频格式转换器哪个最好用
  14. 深度学习-文档检测方案整理
  15. 如何使用苹果官方文档
  16. 起点篇:跨入半导体行业,数字IC设计
  17. 【干货】-- 带你抓取并分析知乎高评分电影
  18. 笔记:OpenCV之眨眼检测
  19. (转)使用自定义行为扩展 WCF
  20. SOA架构和微服务架构的区别(转载)

热门文章

  1. 看到这块Google的“墓地”,心中作何感想?| 今日最佳
  2. 每日一笑 | 在俄罗斯人眼里,没有什么是胶带解决不了的
  3. 每日一笑 | 你知道程序媛最“大”的烦恼是什么吗?
  4. 这一次,用数据解读玩家行为,用实力拿下预测大奖!
  5. php7 不是有效的32位,Win7系统安装软件提示“不是有效的win32应用程序”怎么办?...
  6. 电脑home键在哪_如何灵活使用电脑键盘上的各个键
  7. 通过python实现linux切换用户_Python操作远程服务器切换到root用户
  8. c语言中文件如何插入数据,急求如何将下列C语言程序数据存储到文件中?
  9. 存储mysql数据存在特殊字符时处理_SQL数据库对于保存特殊字符的解决办法
  10. java 传送解析8583报文_java发送ISO8583报文接口案例