Codeforces Round #321 (Div. 2) E - Kefa and Watch(hash + 线段树)
来源:互联网 发布:动态特效的软件 编辑:程序博客网 时间:2024/05/21 16:23
题意:
题意大概是给你一串长度为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 0x3f3f3f3fusing 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 longusing 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;}
0 0
- Codeforces Round #321 (Div. 2) E - Kefa and Watch(hash + 线段树)
- CODEFORCES ROUND #321 (DIV. 2) E.Kefa and Watch(线段树+hash)
- codeforces 321# E. Kefa and Watch (线段树+字符串hash)
- Codeforces 580E Kefa and Watch 线段树+双值Hash
- codeforces 580 E. Kefa and Watch (字符串hash + 线段树)
- codeforces 580 E. Kefa and Watch(hash+线段树)
- CodeForces 580 E.Kefa and Watch(hash+线段树)
- Codeforces #321 E. Kefa and Watch (线段树、哈希)
- Codeforces 580E Kefa and Watch 线段树
- Codeforces Round #321 (Div. 2)E 线段树+字符串hash
- Codeforces Round #321 Kefa and Watch(字符串哈希+线段树)
- 查询[l,r]区间数字串是不是周期为d的串 线段树区间修改+双重hash Codeforces #321 E. Kefa and Watch
- 字符串hash+线段树 Codeforces580E Kefa and Watch
- Codeforces Round #321 (Div. 2) A. Kefa and First Steps
- Codeforces Round #321 (Div. 2) A. Kefa and First Steps
- Codeforces Round #321 (Div. 2)B. Kefa and Company
- Codeforces Round #321 (Div. 2) B. Kefa and Company
- Codeforces Round #321 (Div. 2)C. Kefa and Park
- Android基础学习之navigate(导航)
- 乱记-2
- 万事开头难
- JAVA学习第二天
- 可以匹配就匹配咯: 详解 Swift 的模式匹配
- Codeforces Round #321 (Div. 2) E - Kefa and Watch(hash + 线段树)
- 1044. 火星数字(20)
- Caffe安装 Ubuntu14.04
- 转 JVM内存分析及导致内存溢出的不健壮代码及解决办法
- R使用RMySQL包
- MDM_weeke1
- c# windows form 生命周期 (Life cycle) 事件 顺序
- test
- android WebView的缓存模式、JS交互