【BZOJ1125】【POI2008】Poc 原名:Train hash+离散化+平衡树(splay)

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/45739895");
}

题解:

首先我们发现对于每个串,我们把它hash一下,然后建一棵平衡树来支持“插入”、“删除”、“下传标记”这三种操作就可以记录并更新一个点的答案了。
然后每个串的串长都较小,修改字符时可以暴力重新hash。

注意:

  1. 一对互相交换字符的字符串要先一起删掉再一起往平衡树里加。
  2. 可能是同一个串的俩字符交换,此时不能从平衡树中删两遍。
  3. 德莱文初始攻速接斧头之间只能再A一下(雾,呃觉得两条太单薄

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 305000
#define P 1050
#define ls son[x][0]
#define rs son[x][1]
#define is(x) (son[fa[x]][1]==x)
#define base 233
#define end(i) (n+(i<<1))
using namespace std;
struct GANK
{
    unsigned long long h;
    int v,f,k;
    void read(unsigned _h,int _v,int _f)
        {h=_h,v=_v,f=_f;}
}gank[N];
bool cmph(const GANK &A,const GANK &B){return A.h<B.h;}
bool cmpf(const GANK &A,const GANK &B){return A.f<B.f;}
int ans[N],n,m,p,cnt;
struct SPT
{
    int son[N][2],fa[N],root[N],belong[N],num[N],kda[N];
    void pushdown(int x)
    {
        ans[x]=max(ans[x],kda[x]);
        kda[ls]=max(kda[ls],kda[x]);
        kda[rs]=max(kda[rs],kda[x]);
        kda[x]=0;
    }
    void link(int x,int y,int d){son[y][d]=x,fa[x]=y;}
    void rotate(int x)
    {
        int y,z,i=is(x),t;
        y=fa[x],z=fa[y],t=son[x][!i];
        pushdown(y),pushdown(x);
        link(x,z,is(y)),link(y,x,!i),link(t,y,i);
        son[0][0]=son[0][1]=fa[0]=0;
    }
    void splay(int rt,int x,int d=0)
    {
        int y,z;
        while(fa[x]!=d)
        {
            y=fa[x],z=fa[y];
            if(z==d)rotate(x);
            else rotate(is(x)==is(y)?y:x),rotate(x);
        }
        if(!d)root[rt]=x;
    }
    int succ(int rt,int x)
    {
        splay(rt,x);
        for(x=rs;ls;x=ls);
        return x;
    }
    void insert(int rt,int v)
    {
        int x=root[rt];
        if(!rs)x=ls;
        int suc=succ(rt,x);
        splay(rt,suc,x);
        pushdown(x),pushdown(suc);
        link(v,suc,0),num[rt]++;
        splay(rt,v),kda[v]=num[rt],belong[v]=rt;
    }
    void remove(int rt,int x)
    {
        splay(rt,succ(rt,x));
        splay(rt,x,root[rt]);
        pushdown(root[rt]);
        pushdown(x);
        link(ls,root[rt],0);
        ls=rs=fa[x]=0,num[rt]--;
    }
    void add(int i){insert(gank[i].k,gank[i].v);}
    void rem(int i){remove(belong[gank[i].v],gank[i].v);}
    void init()
    {
        int i,j,k;
        for(i=1;i<=cnt;i++)
        {
            int a=end(i)-1,b=end(i);
            link(b,root[i]=a,1);
        }
        for(i=1;i<=n;i++)add(i);
    }
}spt;
char s[P][P];
unsigned long long baser;
int main()
{
    int i,j,k;
    int a,b,c,d;

    scanf("%d%d%d",&n,&m,&p);
    for(i=1;i<=n;i++)
    {
        scanf("%s",s[i]+1);
        for(baser=0,j=1;j<=m;j++)
            baser=baser*base+s[i][j];
        gank[i].read(baser,i,0);
    }
    for(i=1;i<=p;i++)
    {
        scanf("%d%d%d%d",&a,&b,&c,&d);
        if(s[a][b]==s[c][d])
        {
            i--,p--;
            continue;
        }
        swap(s[a][b],s[c][d]);
        for(baser=0,j=1;j<=m;j++)
            baser=baser*base+s[a][j];
        gank[n+i*2-1].read(baser,a,i);
        for(baser=0,j=1;j<=m;j++)
            baser=baser*base+s[c][j];
        gank[n+i * 2].read(baser,c,i);
    }
    sort(gank+1,gank+n+p*2+1,cmph);
    gank[0].h=gank[1].h^1;
    for(i=1;i<n+p*2+1;i++)
    {
        if(gank[i].h!=gank[i-1].h)cnt++;
        gank[i].k=cnt;
    }
    sort(gank+1,gank+n+p*2+1,cmpf);
    spt.init();
    for(i=1;i<=p;i++)
    {
        b=n+i*2,a=b-1;
        if(gank[a].v==gank[b].v)
            spt.rem(a),spt.add(a);
        else {
            spt.rem(a),spt.rem(b);
            spt.add(a),spt.add(b);
        }
    }
    for(i=1;i<=n;i++)spt.remove(spt.belong[i],i);
    for(i=1;i<=n;i++)printf("%d\n",ans[i]);

    return 0;
}

你可能感兴趣的:(hash,离散化,平衡树,POI2008,BZOJ1125)