G - Caesar Cipher Gym - 102798G
创始人
2024-01-13 04:11:14

题目链接
题意:
1:1 l r表示对[l,r]内的数+1%65536
2:2 l r L 表示[l,l+L-1] 和 [r,r+L-1] 是否一致
题解:
1:线段树维护哈希
2:
哈希的性质:
1:我们对于整段+x,对应的哈希值实际上就是加上了 x*
(相同长度下均为1的数组的哈希值)
2:我们在对应的mod下,以上的操作对应的数加1%mod仍然成立
如:1 2 65535 整体加1 即2 3 65536的哈希值%mod 后与 2 3 0 是一样。

首先上面的结论是正确的,所以我们可以就不用管哪些mod为0的情况,直接算就行,然后就有了下面WA9的代码:

#include
#include
#include
#include
using namespace std;
const int N=5e5+10,mod=65536;typedef unsigned long long ULL;
ULL h[N], p[N],h1[N],P=131; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
// 初始化
int a[N],cop[N],n,m;
void init()
{p[0] = 1;for (int i = 1; i <= n; i ++ ){h[i] = (h[i - 1] * P + a[i])%mod;h1[i]=(h1[i-1] * P + cop[i])%mod;p[i] = (p[i - 1] * P)%mod;}
}
// 计算子串 str[l ~ r] 的哈希值
ULL get(int l, int r)
{return h[r] - h[l - 1] * p[r - l + 1];
}
ULL get1(int l,int r)
{return h1[r] - h1[l - 1] * p[r - l + 1];
}
struct node
{int l,r;ULL has;int lazy;//记录加上了多少
} tr[N*4];
void pushup(int u)
{int len=tr[u<<1|1].r-tr[u<<1|1].l+1;//找到右边的间距tr[u].has=tr[u<<1].has*p[len]%mod;tr[u].has+=tr[u<<1|1].has;//计算当前的hash值tr[u].has%=mod;//一步一模
}
void pushdown(int u,int lazy)
{ULL key=get1(tr[u].l,tr[u].r)*lazy;//找到关键值key%=mod;tr[u].has+=key;tr[u].has%=mod;tr[u].lazy+=lazy;tr[u].lazy%=mod;
}
void pushdown(int u)
{if(tr[u].lazy){pushdown(u<<1,tr[u].lazy);pushdown(u<<1|1,tr[u].lazy);tr[u].lazy=0;}
}
void build(int u,int l,int r)
{tr[u] = {l,r,0,0};if(l==r){tr[u].lazy=0;tr[u].has=get(l,l);tr[u].has%=mod;return;}int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}
void modify(int u,int l,int r)//[l,r]+1;
{if(tr[u].l>=l&&tr[u].r<=r){pushdown(u,1);return;}pushdown(u);int mid=tr[u].l+tr[u].r>>1;if(l<=mid) modify(u<<1,l,r);if(r>mid) modify(u<<1|1,l,r);pushup(u);
}
node query(int u,int l,int r)
{if(tr[u].l>=l&&tr[u].r<=r) return tr[u];pushdown(u);int mid=tr[u].l+tr[u].r>>1;node res1= {0x3f3f3f3f,0,0,0},res2= {0x3f3f3f3f,0,0,0};if(l<=mid) res1=query(u<<1,l,r);if(r>mid) res2=query(u<<1|1,l,r);node res;if(res1.l==0x3f3f3f3f) res=res2;else if(res2.l==0x3f3f3f3f) res=res1;else{res.l=min(res1.l,res2.l);res.r=max(res1.r,res2.r);int len=res2.r-res2.l+1;res.has=res1.has*p[len]%mod;res.has+=res2.has;res.has%=mod;}return res;
}
int main()
{scanf("%d%d",&n,&m);for(int i=1; i<=n; i++) scanf("%d",&a[i]),cop[i]=1;init();build(1,1,n);while(m--){int op,l,r;cin>>op>>l>>r;if(op==1){modify(1,l,r);}if(op==2){int L;cin>>L;node ha1=query(1,l,l+L-1);node ha2=query(1,r,r+L-1);//printf("%llu %llu\n",ha1.has,ha2.has);if(ha1.has==ha2.has) printf("yes\n");else printf("no\n");}}return 0;
}

开始以为这个WA9的代码是某一步mod的问题,改了好久,还是不对.后来才知道,这个题好像可能会卡ULL,所以我们需要用一个质数来mod(例如1e9+7等),但是我们本来只用mod65536相等的数再mod了1e9+7后就不相等了,下面是调试用的代码,可以尝试一下:

#include
#include
#include
#include
using namespace std;
const int N=5e5+10,mod=65536,MOD=1e9+7;
#define int long long   
typedef unsigned long long ULL;
int h[N], p[N],h1[N],P=13331; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64
// 初始化
int a[N],cop[N],n,m;
void init()
{p[0] = 1;for (int i = 1; i <= n; i ++ ){h[i] = (h[i - 1] * P + a[i]);h1[i]=(h1[i-1] * P + cop[i]);p[i] = p[i - 1] * P;}
}
// 计算子串 str[l ~ r] 的哈希值
ULL get(int l, int r)
{return h[r] - h[l - 1] * p[r - l + 1];
}
signed main()
{while(cin>>n){for(int i=1;i<=n;i++) cin>>a[i];init();cout<

我们可以输入以下样例:
4
65536 65536 65536 1
4
0 0 0 1
看两个数相不相等,本来是应该相等的,但实际输出不相等:
25525
1
所以,我们不能用这个mod,就应该直接找到65536然后将他变为0,然后一步一步的求哈希值。这样就可以保证了mod的正确性
下面是AC代码:

#include
#include
#include
#include
using namespace std;
#define int long long
const int N=5e5+10;
const int MOD1=1e9+7;
int h[N], p[N],h1[N],P=13331; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64// 初始化
int a[N],n,m;
void init()
{p[0] = 1;for (int i = 1; i <= n; i ++ ){// h[i] = (h[i - 1] * P + a[i])%MOD1;h1[i]=(h1[i-1] * P + 1)%MOD1;p[i] = (p[i - 1] * P)%MOD1;}
}struct node
{int l,r;int has;int lazy;//记录加上了多少int maxn;
} tr[N*4];
void pushup(int u)
{tr[u].maxn=max(tr[u<<1].maxn,tr[u<<1|1].maxn);int len=tr[u<<1|1].r-tr[u<<1|1].l+1;//找到右边的间距tr[u].has= (tr[u<<1].has*p[len]+ tr[u<<1|1].has)%MOD1;//计算当前的hash值
}void pushdown(int u,int lazy)
{int len=tr[u].r-tr[u].l+1;int key=h1[len]*lazy%MOD1;//找到关键值tr[u].has=(tr[u].has+key)%MOD1;tr[u].maxn+=lazy;tr[u].lazy+=lazy;
}
void pushdown(int u)
{if(tr[u].lazy){pushdown(u<<1,tr[u].lazy);pushdown(u<<1|1,tr[u].lazy);tr[u].lazy=0;}
}void build(int u,int l,int r)
{tr[u].l = l, tr[u].r = r;if(l==r){tr[u].maxn=a[l];tr[u].has=a[l];tr[u].lazy=0;return;}int mid=l+r>>1;build(u<<1,l,mid);build(u<<1|1,mid+1,r);pushup(u);
}void modify(int u,int l,int r)//[l,r]+1;
{if(tr[u].l>=l&&tr[u].r<=r){pushdown(u,1);}else{pushdown(u);int mid=tr[u].l+tr[u].r>>1;if(l<=mid) modify(u<<1,l,r);if(r>mid) modify(u<<1|1,l,r);pushup(u);}}void modify_mod(int u){if(tr[u].maxn<65536) return ;if(tr[u].l==tr[u].r){tr[u].maxn=0;tr[u].has=0;return;}pushdown(u);modify_mod(u<<1);modify_mod(u<<1|1);pushup(u);
}
int query(int u,int l,int r)
{if(tr[u].l>=l&&tr[u].r<=r) return tr[u].has;pushdown(u);int mid=tr[u].l+tr[u].r>>1;int s1=0;int s2=0;if(r>mid) s1=query(u<<1|1,l,r);if(l<=mid) s2=query(u<<1,l,r);int len=max(0ll,min(r,tr[u].r)-mid);s2=s2*p[len]%MOD1;s1=(s1+s2)%MOD1;return s1;
}
signed main()
{scanf("%lld%lld",&n,&m);for(int i=1; i<=n; i++) scanf("%lld",&a[i]);init();build(1,1,n);while(m--){int op,l,r;cin>>op>>l>>r;if(op==1){modify(1,l,r);modify_mod(1);}if(op==2){int Len;cin>>Len;int ha1=query(1,l,l+Len-1);int ha2=query(1,r,r+Len-1);if(ha1==ha2) printf("yes\n");else printf("no\n");}}return 0;
}

就是加了一个modify_mod和多加了一个维护的maxn,主要就是记录区间的最大值,这里的作用主要是对于那个区间内的最大值为65536的数进行再次修改.

总结:
1:hash尽量不用ULL,可以用一个质数去mod
2:就是总结的以的hash的两条性质是正确的

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
阿西吧是什么意思 阿西吧相当于... 即使你没有受到过任何外语培训,你也懂四国语言。汉语:你好英语:Shit韩语:阿西吧(아,씨발! )日...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...