宁波多校 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;
}
View Code

 

以上是关于宁波多校 D题 COLORS的字符串挑战(线段树+hash+二分)的主要内容,如果未能解决你的问题,请参考以下文章

宁波多校 D题 树上的点到链(lca)

宁波多校 G仓鼠的鸡蛋(线段树)

宁波多校 B题 狂赌之渊(dfs+概率)

宁波多校 E题 ddd的逛街计划(Easy Version)

宁波多校 C石头划分(二分)

宁波多校 D. LCA!(换根lca)