宁波多校 D题 COLORS的字符串挑战(线段树+hash+二分)
Posted ctyakwf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了宁波多校 D题 COLORS的字符串挑战(线段树+hash+二分)相关的知识,希望对你有一定的参考价值。
题意:给定一个字符串,每个操作1修改字符串上的某个值
2.给x,y,询问以x开头和以y开头的两个后缀字符串的最长前缀的大小。
经典的线段树维护hash值,之后对于每个询问,用二分查询答案,带了两个log
比赛的时候一直被卡,结束后加了一行如果第一个字母不等就略过的优化就卡过了,太伤了。
#include<cstring> #include<cstdio> #include<set> using namespace std; const int N = 100010, P = 13131; typedef unsigned long long LL; struct note { int l,r; LL h; }tr[N * 4]; char s[N]; LL p[N]; int n; int x,y; void build(int u, int l, int r) { tr[u] = {l, r}; if(l == r) { tr[u].h = s[l]; return; } int mid = l + r >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); tr[u].h = tr[u << 1].h * p[r - mid] + tr[u << 1 | 1].h; } void modify(int u, int x, char c) { if(tr[u].l == tr[u].r) { tr[u].h = c; return; } int mid = tr[u].l + tr[u].r >> 1; if(x <= mid) modify(u << 1, x, c); else modify(u << 1 | 1, x, c); tr[u].h = tr[u << 1].h * p[tr[u].r - mid] + tr[u << 1 | 1].h; } LL query(int u, int l, int r) { if(tr[u].l >= l and tr[u].r <= r) return tr[u].h; int mid = tr[u].l + tr[u].r >> 1; if(r <= mid) return query(u << 1, l, r); else if(l > mid) return query(u << 1 | 1, l, r); return query(u << 1, l, mid) * p[r - mid] + query(u << 1 | 1, l, r); } bool check(int mid){ if(query(1,x,x+mid-1)==query(1,y,y+mid-1)) return true; return false; } int main() { p[0] = 1; for(int i = 1; i < N; i ++) p[i] = p[i - 1] * P; int T; scanf("%d", &T); for(int t = 1; t <= T; t ++) { int n; scanf("%d", &n); scanf("%s", s); build(1, 0, n - 1); int m; scanf("%d", &m); while(m --) { int opt; scanf("%d", &opt); if(opt==2) { scanf("%d%d",&x,&y); if(x>y) swap(x,y); if(s[x]!=s[y]){ printf("0 "); continue; } int l=0,r=n-x; while(l<r){ int mid=l+r+1>>1; if(check(mid)) l=mid; else r=mid-1; } printf("%d ",l); } else { int x; char c[2]; scanf("%d%s", &x, c); modify(1, x, c[0]); s[x]=c[0]; } } } return 0; }
以上是关于宁波多校 D题 COLORS的字符串挑战(线段树+hash+二分)的主要内容,如果未能解决你的问题,请参考以下文章