【gdgzezoi】問題B:フォーニ

説明

あなたはn個の要素Pの列があり、lenの初期長さは、文字列Sを与えます

次に、m個の動作は、3つのタイプ、すなわち、存在します。

  1. 文字列の前に追加されます
  2. 要素Pの値を変更します
  3. S [LP [I] + 1 ... L] iが辞書最小(複数の出力の最小値iは、Lは、現在の文字列の長さである)ように、全てのi∈[L、R]を求めます

(力によって)

入力

入力コモンラインm + 3。
三つの整数N、Mの最初の行は、lenの。
第2行動の初期文字列S.
第三行、数N、P [1] ... P [N ]。
続いて行をM、各列は、演算を表します。

  1. lastans上で最も前に位置で最初のI C(C XOR lastans)+1小文字の文字列の追加

       次Q询问的答案,初始为0。
    
  2. C xはPOS P [X]は、POSに修正されます。

  3. プレゼントLR Qは[L ... R]間隔を依頼します。

出力

对于每个Q询问输出一行,表示答案。

サンプル入力

3 3 5

horni

3 2 5

I 15

C 1〜6

Q 1 3

サンプル出力

3

ヒント

データの10%、1 <= N <= 100,1 <= M <= 100,1 <= LEN <= 100,1 <= P [i]は<= LEN。

データの100%に、1 <= N <= 500000,1 <= M <= 800000,1 <= LEN <= 100000,1 <= P [i]は<= LEN。

I動作、0 <= C XOR lastans <= 25。
操作C 1 <= X <= N、 1 <= POS <= 現在の文字列の長さ。
Q動作1 <= L、R <= nです。

操作量1/5の操作の総数のI、C、Q各操作の総数の2/5約操作の数。

思考

サフィックスバランスの取れたツリー。私は、最小のメンテナンス間隔Pサフィックスアレイ、改変、及び呼び掛けセグメントツリーは簡単な操作セグメントツリーは、バランスのとれたツリー新たに追加されたサフィックスで動作しています。

コード

#include<bits/stdc++.h>
#define ll long long
using namespace std;
typedef pair<int,int> pii;
typedef pair<ll,int> pli;
const ll inf=0x7fffffffffffffff;
int p[2000077];
char s[2000077];
ll rk[2000077];
int cmp(int x,int y)
{
    if(s[x]!=s[y])
        return s[x]<s[y];
    return rk[x-1]<rk[y-1];
}
struct suf
{
    int x;
    suf(int a=0)
    {
        x=a;
    }
};
int operator <(suf a,suf b)
{
    return cmp(a.x,b.x);
}
typedef pair<suf,int> psi;
namespace sgt
{
    int ls[1000010];
    int rs[1000010];
    psi s[1000010];
    int cnt=0;
    int rt;
    void build(int &p,int l,int r)
    {
        p=++cnt;
        if(l==r)
            return;
        int mid=(l+r)>>1;
        build(ls[p],l,mid);
        build(rs[p],mid+1,r);
    }
    void change(int p,int x,psi v,int L,int R)
    {
        if(L==R)
        {
            s[p]=v;
            return;
        }
        int mid=(L+R)>>1;
        if(x<=mid)
            change(ls[p],x,v,L,mid);
        else
            change(rs[p],x,v,mid+1,R);
        s[p]=min(s[ls[p]],s[rs[p]]);
    }
    psi query(int p,int l,int r,int L,int R)
    {
        if(l<=L&&r>=R)
            return s[p];
        int mid=(L+R)>>1;
        if(r<=mid)
            return query(ls[p],l,r,L,mid);
        if(l>mid)
            return query(rs[p],l,r,mid+1,R);
        return min(query(ls[p],l,r,L,mid),query(rs[p],l,r,mid+1,R));
    }
};
namespace sct
{
    struct node
    {
        int v;
        int s;
        int ls,rs;
        ll k;
        ll l,r;
    };
    node a[2000010];
    int cnt=0;
    int rt=0;
    int *b;
    void insert(int &p,int v,ll l,ll r)
    {
        if(!p)
        {
            p=++cnt;
            a[p].s=1;
            a[p].v=v;
            a[p].l=l;
            a[p].r=r;
            a[p].k=l+((r-l)>>1);
            a[p].ls=a[p].rs=0;
            rk[v]=a[p].k;
            return;
        }
        a[p].s++;
        if(cmp(v,a[p].v))
        {
            insert(a[p].ls,v,l,a[p].k-1);
            if(a[a[p].ls].s>a[p].s*0.7)
                b=&p;
        }
        else
        {
            insert(a[p].rs,v,a[p].k+1,r);
            if(a[a[p].rs].s>a[p].s*0.7)
                b=&p;
        }
    }
    int t;
    int c[1000010];
    int d[1000010];
    void dfs(int &p)
    {
        if(a[p].ls)
            dfs(a[p].ls);
        c[++t]=p;
        d[t]=a[p].v;
        if(a[p].rs)
            dfs(a[p].rs);
        p=0;
    }
    void build(int &p,int l,int r,ll L,ll R)
    {
        int mid=(l+r)>>1;
        ll k=L+((R-L)>>1);
        p=c[mid];
        a[p].v=d[mid];
        rk[a[p].v]=k;
        a[p].l=L;
        a[p].r=R;
        a[p].s=r-l+1;
        a[p].k=k;
        a[p].ls=a[p].rs=0;
        if(l<mid)
            build(a[p].ls,l,mid-1,L,k-1);
        if(r>mid)
            build(a[p].rs,mid+1,r,k+1,R);
    }
    void build()
    {
        ll l=a[*b].l;
        ll r=a[*b].r;
        t=0;
        dfs(*b);
        build(*b,1,t,l,r);
    }
}
int main()
{
    int n,m,len;
    scanf("%d%d%d",&n,&m,&len);
    scanf("%s",s+1);
    reverse(s+1,s+len+1);
    rk[0]=-1;
    int i;
    for(i=1;i<=len;i++)
    {
        sct::b=0;
        sct::insert(sct::rt,i,0,inf);
        if(sct::b)
            sct::build();
    }
    char op[5];
    int last=0;
    int x,y;
    sgt::build(sgt::rt,1,n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        sgt::change(sgt::rt,i,psi(suf(x),i),1,n);
    }
    for(i=1;i<=m;i++)
    {
        scanf("%s",op);
        if(op[0]=='I')
        {
            scanf("%d",&x);
            x^=last;
            s[++len]=x+'a';
            sct::b=0;
            sct::insert(sct::rt,len,0,inf);
            if(sct::b)
                sct::build();
        }
        else if(op[0]=='C')
        {
            scanf("%d%d",&x,&y);
            sgt::change(sgt::rt,x,psi(suf(y),x),1,n);
        }
        else
        {
            scanf("%d%d",&x,&y);
            psi ans=sgt::query(sgt::rt,x,y,1,n);
            last=ans.second;
            printf("%d\n",last);
        }
    }
    return 0;
}

703元記事公開 ウォンの賞賛392 ビューに14万+を

おすすめ

転載: blog.csdn.net/Eric1561759334/article/details/100587205