MnZn 求助 30pts
查看原帖
MnZn 求助 30pts
420129
Nt_Tsumiki楼主2024/7/21 19:33

rt

目测是比答案大了。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>

#define N 200001
#define LL long long

using namespace std;
int n,q;
string s;

int tcnt,rt[N];
struct Tree { int ls,rs,mn,mx; LL sum1,sum2; }t[N<<6];

Tree pushup(Tree a,Tree b) {
    return {0,0,min(a.mn,b.mn),max(a.mx,b.mx),
        a.sum1+b.sum1+(b.mn!=1e9 and a.mx?1ll*(b.mn-a.mx)*b.mn:0),
        a.sum2+b.sum2+(b.mn!=1e9 and a.mx?b.mn-a.mx:0)};
}

void upd(int &x,int l,int r,int pos) {
    if (!x) x=++tcnt;
    if (l==r) return t[x]={0,0,l,l,0,0},void();
    int mid=(l+r>>1);
    if (pos<=mid) upd(t[x].ls,l,mid,pos);
    else upd(t[x].rs,mid+1,r,pos);
    t[x].mn=min(t[t[x].ls].mn,t[t[x].rs].mn);
    t[x].mx=max(t[t[x].ls].mx,t[t[x].rs].mx);
    t[x].sum1=t[t[x].ls].sum1+t[t[x].rs].sum1
                +(t[t[x].rs].mn!=1e9 and t[t[x].ls].mx?1ll*(t[t[x].rs].mn-t[t[x].ls].mx)*t[t[x].rs].mn:0);
    t[x].sum2=t[t[x].ls].sum2+t[t[x].rs].sum2
                +(t[t[x].rs].mn!=1e9 and t[t[x].ls].mx?t[t[x].rs].mn-t[t[x].ls].mx:0);
}

int merge(int x,int y,int l,int r) {
    if (!x or !y) return x|y;
    int rt=++tcnt;
    if (l==r) return t[rt]={0,0,l,l,0,0},rt;
    int mid=(l+r>>1);
    t[rt].ls=merge(t[x].ls,t[y].ls,l,mid);
    t[rt].rs=merge(t[x].rs,t[y].rs,mid+1,r);
    t[rt].mn=min(t[t[rt].ls].mn,t[t[rt].rs].mn);
    t[rt].mx=max(t[t[rt].ls].mx,t[t[rt].rs].mx);
    t[rt].sum1=t[t[rt].ls].sum1+t[t[rt].rs].sum1
                +(t[t[rt].rs].mn!=1e9 and t[t[rt].ls].mx?1ll*(t[t[rt].rs].mn-t[t[rt].ls].mx)*t[t[rt].rs].mn:0);
    t[rt].sum2=t[t[rt].ls].sum2+t[t[rt].rs].sum2
                +(t[t[rt].rs].mn!=1e9 and t[t[rt].ls].mx?t[t[rt].rs].mn-t[t[rt].ls].mx:0);
    return rt;
}

Tree ask(int x,int l,int r,int L,int R) {
    if (!x or L>R) return t[0];
    if (L<=l and r<=R) return t[x];
    int mid=(l+r>>1);
    if (R<=mid) return ask(t[x].ls,l,mid,L,R);
    else if (L>mid) return ask(t[x].rs,mid+1,r,L,R);
    else return pushup(ask(t[x].ls,l,mid,L,R),ask(t[x].rs,mid+1,r,L,R));
}

int tot=1,np=1,ch[N][10],len[N],fail[N],pos[N];

void ins(int c,int Pos) {
    int p=np; len[pos[Pos]=np=++tot]=len[p]+1;
    upd(rt[np],1,n,Pos);
    while (p and !ch[p][c]) ch[p][c]=np,p=fail[p];
    if (!p) fail[np]=1;
    else {
        int q=ch[p][c];
        if (len[q]==len[p]+1) fail[np]=q;
        else {
            int nq=++tot;
            len[nq]=len[p]+1,fail[nq]=fail[q];
            fail[q]=fail[np]=nq;
            memcpy(ch[nq],ch[q],sizeof ch[q]);
            while (p and ch[p][c]==q) ch[p][c]=nq,p=fail[p];
        }
    }
}

int cnt,head[N];
struct Node { int to,nxt; }e[N];

void add(int u,int v) { e[++cnt]=Node{v,head[u]},head[u]=cnt; }

int fa[N][20];

void dfs0(int u) {
    fa[u][0]=fail[u];
    for (int i=1;i<20;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
    for (int i=head[u];i;i=e[i].nxt) {
        int v=e[i].to;
        dfs0(v);
        rt[u]=merge(rt[u],rt[v],1,n);
    }
}

int main() {
    scanf("%d%d",&n,&q);
    cin>>s;
    t[0]={0,0,(int)1e9,0,0,0};
    for (int i=0;i<n;i++) ins(s[i]-'0',i+1);
    for (int i=2;i<=tot;i++) add(fail[i],i);
    dfs0(1);
    for (int i=1,l,r;i<=q;i++) {
        scanf("%d%d",&l,&r);
        if (l>r or l<1 or l>n or r<1 or r>n) {
            printf("%lld\n",1ll*(n-1)*(n-2)/2);
            continue;
        }
        int p=pos[r];
        for (int i=19;i>=0;i--)
            while (len[fa[p][i]]>=r-l+1) p=fa[p][i];
        int mn=t[rt[p]].mn,mx=t[rt[p]].mx;
        LL sum1=t[rt[p]].sum1,sum2=t[rt[p]].sum2;
        Tree tmp1=ask(rt[p],1,n,mx-(r-l),mn+(r-l)),
            tmp2=ask(rt[p],1,n,mn,mx-(r-l+1)),
            tmp3=ask(rt[p],1,n,1,mn+(r-l)),
            tmp4=ask(rt[p],1,n,mn+(r-l)+1,n);
        if (tmp2.mx and tmp2.mx-mn>=r-l+1 and mx-tmp2.mx>=r-l+1) printf("%lld\n",1ll*(n-1)*(n-2)/2);
        else if (mn>=mx-(r-l)) 
            printf("%lld\n",1ll*(n-1)*(n-2)/2-(sum1-sum2*(mx-(r-l))
                +1ll*(mn-(mx-(r-l)))*(mn-(mx-(r-l))-1)/2
                +1ll*(mn-(mx-(r-l)))*(n-(r-l+1))));
        else
            printf("%lld\n",1ll*(n-1)*(n-2)/2-(tmp1.sum1-tmp1.sum2*(mx-(r-l))
                +(tmp4.mn>(mx-(r-l))?1ll*(mn-(tmp3.mx-(r-l)))*(tmp4.mn-(mx-(r-l))):0)));
    }
    return 0;
}
2024/7/21 19:33
加载中...