题意:
题意大概是给你一串长度为n的数字串,两个操作,1 l r c 将 下标为l 到 r 的数字全部改为 c
2 l r c 询问 下标为l 到 r 的数字 循环节是否为 c
n 的范围是10W, 第二个c的范围是10
思路:
做法就是字符串hash啦,因为字符串hash类似于前缀和的处理,也就是说:比如区间 (v1)[L,mid 和区间 (v2)mid+1 , R 合并成
L , R 。那么区间L,R 的值就是 v2+v1∗Plengthv2 ,这样的话,是不是就可以去用线段树查询或者是区间更新维护了呢?
两份代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <string>
#define PB push_back
#define FT first
#define SD second
#define MP make_pair
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=5+1e5;
const LL MOD=7+1e9;
const LL seed=49681;;
LL pw[N];
int n,lazy[4*N];
LL ch[11][N],H[4*N];
void init()
{
pw[0]=1LL;
for(int i=1;i<=n;i++) {
pw[i] = pw[i-1]*seed % MOD;
}
for(int i=1;i<=10;i++){
ch[i][0]=0;
for(int j=1;j<=n;j++) {
ch[i][j]=(ch[i][j-1]*seed%MOD + i) %MOD ;
}
}
}
void pushdown(int rt,int L,int R)
{
int T=lazy[rt],mid=(L+R)>>1;
lazy[rt]=0;
lazy[2*rt]=lazy[2*rt+1]=T;
H[2*rt]=ch[T][mid-L+1],H[2*rt+1]=ch[T][R-mid];
}
void update(int rt,int L,int R,int l,int r,int v)
{
if(l<=L && R<=r) {
H[rt] = ch[v][r-l+1];
//cout<<v<<" "<<l<<" "<<r<<" "<<H[rt]<<endl;
lazy[rt]=v;
return ;
}
else {
int mid=(L+R)>>1;
if(lazy[rt]) pushdown(rt,L,R);
if(r<=mid) update(rt*2,L,mid,l,r,v);
else if(l>mid) update(2*rt+1,mid+1,R,l,r,v);
else {
update(2*rt,L,mid,l,mid,v);
update(2*rt+1,mid+1,R,mid+1,r,v);
}
H[rt] = (H[rt*2]*pw[R-mid]%MOD+H[2*rt+1])%MOD;
}
}
LL query(int rt,int L,int R,int l,int r)
{
//cout<<L<<" "<<R<<" "<<l<<" "<<r<<endl;
if(l<=L && R<=r) {
//cout<<"NOW: "<<l<<" "<<r<<" "<<H[rt]<<endl;
return H[rt];
}
else {
int mid=(L+R)>>1;
if(lazy[rt]) {
pushdown(rt,L,R);
//cout<<"pushdown: "<<L<<" "<<R<<endl;
}
if(r<=mid) return query(rt*2,L,mid,l,r);
else if(l>mid) return query(2*rt+1,mid+1,R,l,r);
else {
LL a=query(2*rt,L,mid,l,mid);
LL b=query(2*rt+1,mid+1,R,mid+1,r);
return (a*pw[r-mid] % MOD + b) % MOD;
}
}
}
bool check(int L,int R,int d)
{
if(d>=R-L+1) return true;
return query(1,1,n,L,R-d)==query(1,1,n,L+d,R);
}
char ss[N];
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int m,k;
scanf("%d%d%d",&n,&m,&k);
init();
scanf("%s",ss+1);
for(int i=1;i<=n;i++) {
update(1,1,n,i,i,ss[i]-'0'+1);
}
m+=k;
while(m--){
int tp,l,r,d;
scanf("%d%d%d%d",&tp,&l,&r,&d);
if(tp == 1){
update(1,1,n,l,r,d+1);
}
else {
printf("%s\n", check(l,r,d)?"YES":"NO");
}
}
//system("pause");
return 0;
}
还有队友写的一种风格,Orz
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int MAXN = 100000+50;
const int P = 1e9+7;
int n, m, k;
int p[MAXN], ch[10][MAXN];
struct Node{
int l, r, h, len, lazy;
int mid() {
return (l + r) / 2;
}
void pushdown(int v) {
lazy = v;
h = ch[v][len];
}
}tree[MAXN*4];
int merge(int h1, int h2, int len)
{
// cout << h1 << ' ' << h2 << ' ' << len << endl;
if (len > 0)
return (h1 + (ll)h2 * p[len] % P) % P;
else
return h2;
}
void build(int l, int r, int idx)
{
tree[idx].l = l; tree[idx].r = r;
tree[idx].len = (r - l + 1);
tree[idx].lazy = -1;
if (l == r) {
tree[idx].h = getchar() - '0';
return;
}
int mid = tree[idx].mid();
build(l, mid, idx*2);
build(mid+1, r, idx*2+1);
tree[idx].h = merge(tree[idx*2].h, tree[idx*2+1].h, tree[idx*2].len);
// cout << l << ' ' << r << ' ' << tree[idx]. h << endl;
}
void update(int l, int r, int v, int idx)
{
if (l > r)
return;
if (l == tree[idx].l && r == tree[idx].r) {
tree[idx].pushdown(v);
tree[idx].lazy = v;
return;
}
if (tree[idx].lazy != -1) {
tree[idx*2].pushdown(tree[idx].lazy);
tree[idx*2+1].pushdown(tree[idx].lazy);
tree[idx].lazy = -1;
}
int mid = tree[idx].mid();
update(l, min(mid, r), v, idx*2);
update(max(mid+1, l), r, v, idx*2+1);
tree[idx].h = merge(tree[idx*2].h, tree[idx*2+1].h, tree[idx*2].len);
}
int query(int l, int r, int idx)
{
if (l > r)
return 0;
if (l == tree[idx].l && r == tree[idx].r) {
return tree[idx].h;
}
if (tree[idx].lazy != -1) {
tree[idx*2].pushdown(tree[idx].lazy);
tree[idx*2+1].pushdown(tree[idx].lazy);
tree[idx].lazy = -1;
}
int mid = tree[idx].mid();
return merge(query(l, min(r, mid), idx*2), query(max(mid+1, l), r, idx*2+1), min(mid, r)-l+1);
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
m += k;
p[0] = 1;
for (int i = 1; i < n; i++)
p[i] = (ll)p[i-1] * 451309 % P;
for (int i = 0; i < 10; i++) {
for (int j = 1; j <= n; j++)
ch[i][j] = (ch[i][j-1] + (ll)i * p[j-1] % P) % P;
}
getchar();
build(1, n, 1);
while (m--) {
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
if (a == 1)
update(b, c, d, 1);
else
printf("%s\n", query(b, c-d, 1) == query(b+d, c, 1) ? "YES" : "NO");
}
return 0;
}