JSOI2008火星人

Posted HellPix

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JSOI2008火星人相关的知识,希望对你有一定的参考价值。

题面

https://www.luogu.org/problem/P4036

题解

#include<cstdio>
#include<iostream>
#include<cstring>
#define ri register int
#define N 105000
#define uLL unsigned long long
using namespace std;

const uLL p=107;
uLL pp[N];
char s[N],op[3],c[5];
int n,a,b,ptt;

struct Splay{
  int ch[N][2],f[N],siz[N];
  uLL sum[N],v[N];
  int tot;
  void clear() {tot=1; siz[1]=1;}  // &&&***
  bool opt(int x) {return ch[f[x]][1]==x;} 
  int new_node(int x,int ff) {
    ++tot;
    sum[tot]=v[tot]=x; // &&&***
    siz[tot]=1;
    f[tot]=ff;
    return tot;
  }
  void pushup(int x) {
    if (!x) return; // &&&***
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    sum[x]=sum[ch[x][0]]+v[x]*pp[siz[ch[x][0]]]+sum[ch[x][1]]*pp[siz[ch[x][0]]+1];
  }
  void rotate(int x) {
    int y=f[x],z=f[y],s=opt(x),w=ch[x][1^s];
    f[x]=z; ch[z][opt(y)]=x;
    ch[y][s]=w; if (w) f[w]=y;
    f[y]=x; ch[x][1^s]=y;
    pushup(y); pushup(x);
  }
  void splay(int at,int to) {
    while (1) {
      if (f[at]==to) return;
      if (f[f[at]]==to) rotate(at);
      else {
        if (opt(at)==opt(f[at])) rotate(f[at]),rotate(at);
        else rotate(at),rotate(at);
      }
    }
  }
  int findbyrank(int x){
    int les=0,now=1;
    while (1) {
      if (les+siz[ch[now][0]]==x) return now;
      else if (les+siz[ch[now][0]]>x) now=ch[now][0]; else les+=siz[ch[now][0]]+1,now=ch[now][1];
    }
  }
  uLL getval(int l,int r) {
    int x=findbyrank(l-1);
    splay(x,1);
    if (r==ptt) return sum[ch[x][1]];
    else {
      int y=findbyrank(r+1);
      splay(y,x);
      return sum[ch[y][0]]; // &&&***
    }
  }
} t;

int main() {
  //freopen("tt.in","r",stdin);
  pp[0]=1;
  for (ri i=1;i<N;i++) pp[i]=pp[i-1]*p;
  scanf("%s",s+1);
  int L=strlen(s+1);
  t.clear();
  for (ri i=1;i<=L;i++) {
    int x=t.findbyrank(i-1);
    t.splay(x,1);
    t.ch[x][1]=t.new_node(s[i]-a,x);
    t.pushup(x);
  }
  scanf("%d",&n);
  ptt=L;
  while (n--) {
    scanf("%s",op);
    if (op[0]==Q) {
      scanf("%d %d",&a,&b);
      int Lb=1,Rb=min(ptt-a+1,ptt-b+1),ans=0;
      while (Lb<=Rb) {
        int mid=(Lb+Rb)/2;
        uLL t1=t.getval(a,a+mid-1);
        uLL t2=t.getval(b,b+mid-1);
        //cout<<t1<<" "<<t2<<endl;
        if (t1==t2) ans=mid,Lb=mid+1; else Rb=mid-1;
      }
      printf("%d\n",ans);
    }
    else if (op[0]==I) {
      scanf("%d %s",&a,c);
      int x=t.findbyrank(a);
      t.splay(x,1);
      if (a==ptt) {
        t.ch[x][1]=t.new_node(c[0]-a,x);
        t.pushup(x);
      }
      else {
        int y=t.findbyrank(a+1);
        t.splay(y,x);
        t.ch[y][0]=t.new_node(c[0]-a,y); // &&&***
        t.pushup(y); t.pushup(x);  // &&&***
      }
      ptt++;
    }
    else if (op[0]==R) {
      scanf("%d %s",&a,c);
      int x=t.findbyrank(a);
      t.splay(x,1);
      t.v[x]=c[0]-a;
      t.pushup(x);
    }
  }
  return 0;
}

以上是关于JSOI2008火星人的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1014[JSOI2008]火星人prefix

bzoj1014: [JSOI2008]火星人prefix

[JSOI2008]火星人prefix

JSOI2008火星人

[JSOI2008]火星人

[BZOJ1014][JSOI2008]火星人prefix