• BZOJ3682 : Phorni


    后缀平衡树+线段树。

    $O(1)$比较大小的标号法真是强大。

    #include<cstdio>
    #include<cmath>
    #define N 300010
    #define M 500010
    using namespace std;
    typedef unsigned long long ll;
    const ll inf=1ULL<<63;
    const double A=0.8;
    ll tl[N],tr[N],tm[N];
    int size[N],son[N][2],f[N],v[N],tot,root,id[N],cnt;
    char s[N],ch;
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline bool cmp(int a,int b){return s[a]==s[b]?tm[a-1]>tm[b-1]:s[a]>s[b];}
    int ins(int x,int p){
      int b=cmp(p,v[x]);
      if(!son[x][b]){
        son[x][b]=++tot;f[tot]=x;v[tot]=p;
        if(!b)tl[tot]=tl[x],tr[tot]=tm[x];else tl[tot]=tm[x],tr[tot]=tr[x];
        tm[tot]=(tl[tot]+tr[tot])>>1;
        return tot;
      }else return ins(son[x][b],p);
    }
    void dfs(int x){
      if(son[x][0])dfs(son[x][0]);
      id[++cnt]=x;
      if(son[x][1])dfs(son[x][1]);
    }
    int build(int fa,int l,int r,ll a,ll b){
      int mid=(l+r)>>1,x=id[mid];
      f[x]=fa;son[x][0]=son[x][1]=0;size[x]=1;tl[x]=a;tr[x]=b;tm[x]=(a+b)>>1;
      if(l==r)return x;
      if(l<mid)size[x]+=size[son[x][0]=build(x,l,mid-1,a,tm[x])];
      if(r>mid)size[x]+=size[son[x][1]=build(x,mid+1,r,tm[x],b)];
      return x;
    }
    inline int rebuild(int x){
      cnt=0;dfs(x);return build(f[x],1,cnt,tl[x],tr[x]);
    }
    inline void insert(int p){
      if(!root){root=tot=size[1]=1;v[1]=p;tr[1]=inf,tm[1]=inf>>1;return;}
      int x=ins(root,p);
      int deep=0,z=x;while(z)size[z]++,z=f[z],deep++;
      if(deep<log(tot)/log(1/A))return;
      while((double)size[son[x][0]]<A*size[x]&&(double)size[son[x][1]]<A*size[x])x=f[x];
      if(!x)return;
      if(x==root){root=rebuild(x);return;}
      int y=f[x],b=son[y][1]==x,now=rebuild(x);
      son[y][b]=now;
    }
    int l[M<<1],r[M<<1],min[M<<1],seq[M],TOT;
    void build(int a,int b){
      int x=++TOT;
      if(a==b){min[x]=a;return;}
      int mid=(a+b)>>1;
      l[x]=TOT+1;build(a,mid);
      r[x]=TOT+1;build(mid+1,b);
      min[x]=tm[seq[min[l[x]]]]<=tm[seq[min[r[x]]]]?min[l[x]]:min[r[x]];
    }
    void change(int x,int a,int b,int c){
      if(a==b)return;
      int mid=(a+b)>>1;
      if(c<=mid)change(l[x],a,mid,c);else change(r[x],mid+1,b,c);
      min[x]=tm[seq[min[l[x]]]]<=tm[seq[min[r[x]]]]?min[l[x]]:min[r[x]];
    }
    int ask(int x,int a,int b,int c,int d){
      if(c<=a&&b<=d)return min[x];
      int mid=(a+b)>>1,i,j;
      if(d<=mid)return ask(l[x],a,mid,c,d);
      if(c>mid)return ask(r[x],mid+1,b,c,d);
      i=ask(l[x],a,mid,c,d),j=ask(r[x],mid+1,b,c,d);
      return tm[seq[i]]<=tm[seq[j]]?i:j;
    }
    int n,m,i,x,y,len,type,ans;
    int main(){
      read(n);read(m);read(len);read(type);
      for(getchar(),i=1;i<=len;i++)s[len-i+1]=getchar();
      for(i=1;i<=len;i++)insert(i);
      for(i=1;i<=n;i++)read(seq[i]);
      build(1,n);
      while(m--){
        while(!(((ch=getchar())=='I')||(ch=='C')||(ch=='Q')));read(x);
        if(ch=='I')s[++len]=(x^ans*type)+'a',insert(len);
        if(ch=='C')read(seq[x]),change(1,1,n,x);
        if(ch=='Q')read(y),printf("%d
    ",ans=ask(1,1,n,x,y));
      }
      return 0;
    }
    

      

  • 相关阅读:
    常用集体名词的用法
    囊中羞涩的表达
    《当幸福来敲门》观后感
    <肖申克的救赎>观后感
    心语4
    补充:回答网友的问题,如何不用路径,而直接将CImage画到DC中,之后DC一起显示.
    线程中对变量的用法
    添加按键变量数组,就是很多同种类型按键关联变量,这些变量是一个数组;
    不容按钮、下拉框 执行同一个函数或者同一种函数的用法
    CImage显示位图与CDC双缓冲冲突,使用路径层解决.
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403222.html
Copyright © 2020-2023  润新知