题目链接
题意不难,给你一段长度为N的字符串,接下来就是有两种操作:一是更新一段区间让它们的值相同;二是问这个查询的区间是否符合f(i)==f(i+d),就是是否以d为周期长度。
思路:
确实想了挺久的,首先是字符串,这里就需要用到哈希的方式来处理,一开始哈希没弄好,错了,后来再重做时加上了取mod的操作然后就过了,还有,如何判断它是一个以d为周期长度的字符串呢?就利用f(i)==f(i+d)不就可以了吗,但是查询区间有长度[l, r],所以我们可以查询[l, r-d]与[l+d, r]是否相等不就是满足条件了,还有一件事,题目中说道1 ≤ d ≤ r - l + 1,但是d==(r-l+1)的时候刚哈就是满区间,所以肯定是个以d为周期长度的字符串了。
完整代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const ull Hash1=131, Hash2=233;
const ull mod=1e9+7;
const int maxN=1e5+5;
int N, M, Q;
ull ba1[maxN], ba2[maxN], val_1[10][maxN], val_2[10][maxN];
int lazy[maxN<<2];
char s[maxN];
struct node
{
ull sum1, sum2;
int l, r;
node(ull a=0, ull b=0, int c=0, int d=0):sum1(a), sum2(b), l(c), r(d) {}
}tree[maxN<<2];
void pre_did() //预处理
{
ba1[0]=ba2[0]=1;
for(int i=1; i<maxN; i++)
{
ba1[i]=ba1[i-1] * Hash1 %mod;
ba2[i]=ba2[i-1] * Hash2 %mod;
}
for(int i=0; i<10; i++) val_1[i][0]=val_2[i][0]=0;
for(int i=0; i<10; i++)
{
for(int j=1; j<maxN; j++)
{
val_1[i][j]=( val_1[i][j-1] * Hash1 %mod+i )%mod;
val_2[i][j]=( val_2[i][j-1] * Hash2 %mod+i )%mod;
}
}
}
void pushup(int rt)
{
int lenr = tree[rt<<1|1].r - tree[rt<<1|1].l+1;
tree[rt].sum1 =( tree[rt<<1].sum1 * ba1[lenr] + tree[rt<<1|1].sum1 )%mod;
tree[rt].sum2 =( tree[rt<<1].sum2 * ba2[lenr] + tree[rt<<1|1].sum2 )%mod;
}
void buildTree(int rt, int l, int r)
{
tree[rt].l=l; tree[rt].r=r; lazy[rt]=-1;
if(l==r)
{
tree[rt].sum1=tree[rt].sum2=s[l]-'0';
return;
}
int mid=( l + r )>>1;
buildTree(rt<<1, l, mid);
buildTree(rt<<1|1, mid+1, r);
pushup(rt);
}
void pushdown(int rt)
{
if(lazy[rt]!=-1)
{
lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
tree[rt<<1].sum1 = val_1[lazy[rt]][tree[rt<<1].r-tree[rt<<1].l+1];
tree[rt<<1].sum2 = val_2[lazy[rt]][tree[rt<<1].r-tree[rt<<1].l+1];
tree[rt<<1|1].sum1 = val_1[lazy[rt]][tree[rt<<1|1].r-tree[rt<<1|1].l+1];
tree[rt<<1|1].sum2 = val_2[lazy[rt]][tree[rt<<1|1].r-tree[rt<<1|1].l+1];
lazy[rt]=-1;
}
}
void update(int rt, int l, int r, int ql, int qr, int val)
{
if(ql<=l && qr>=r)
{
lazy[rt] = val;
tree[rt].sum1 = val_1[val][tree[rt].r-tree[rt].l+1];
tree[rt].sum2 = val_2[val][tree[rt].r-tree[rt].l+1];
return;
}
pushdown(rt);
int mid=(l + r)>>1;
if(ql>mid) update(rt<<1|1, mid+1, r, ql, qr, val);
else if(qr<=mid) update(rt<<1, l, mid, ql, qr, val);
else
{
update(rt<<1, l, mid, ql, mid, val);
update(rt<<1|1, mid+1, r, mid+1, qr, val);
}
pushup(rt);
}
void query(int rt, int l, int r, int ql, int qr, ull &tmp1, ull &tmp2)
{
if(ql<=l && qr>=r)
{
tmp1 = ( tmp1 + tree[rt].sum1*ba1[qr-r] )%mod;
tmp2 = ( tmp2 + tree[rt].sum2*ba2[qr-r] )%mod;
}
else
{
int mid=(l + r)>>1;
pushdown(rt);
if(ql<=mid) query(rt<<1, l, mid, ql, qr, tmp1, tmp2);
if(qr>mid) query(rt<<1|1, mid+1, r, ql, qr, tmp1, tmp2);
}
}
int main()
{
pre_did();
while(scanf("%d%d%d", &N, &M, &Q)!=EOF)
{
Q+=M;
scanf("%s", s+1);
buildTree(1, 1, N);
while(Q--)
{
int pd, l, r, d;
scanf("%d%d%d%d", &pd, &l, &r, &d);
if(pd==1)
{
update(1, 1, N, l, r, d);
}
else
{
if(r-l+1 <= d)
{
printf("YES\n");
continue;
}
ull tp11=0, tp12=0;
query(1, 1, N, l, r-d, tp11, tp12);
ull tp21=0, tp22=0;
query(1, 1, N, l+d, r, tp21, tp22);
if(tp11==tp21 && tp12==tp22) printf("YES\n");
else printf("NO\n");
}
}
}
return 0;
}