UVa11996 splay树(WA)

写了200多行,总是WA,我也实在看不出哪里错了。。

估计问题还在于翻转和查询LCP的地方,可是用10以内的小数据测怎么变都是对的。。

郁闷ing。。

几个细节:

用指针null代替NULL,方便了很多,等于最后叶子节点都指向null,不必每次判断左右子树指针是否为空;

可能我的hash有点问题,我是每次把mid长度的序列从中切下来,得到hash,然后合起来在切开,得到hash2,然后比较,感觉这样比较慢,应该是logn^2的复杂度;

究竟错在哪里,写成这样,很难调啊。。

#include <fstream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

//#define N 400000+5
#define N 200
#define x 89
char str[N];
unsigned long long xp[N];

struct Node {
    Node* ch[2];
    int v;//value
    int size;//sum
    int rank;//current tree's position
    int flip;//rotate flag
    unsigned long long h,cvh;//hash

    int cmp(int k) const {
        if (k==rank) return -1;
        return k<rank? 0 : 1;
    }

    void pushdown(Node* null){
        if (flip) {
            flip=0;
            swap(ch[0],ch[1]);
            if(ch[0]!=null) ch[0]->flip = !ch[0]->flip;
            if(ch[1]!=null) ch[1]->flip = !ch[1]->flip;
        }
    }

    void maintain(Node* null){
        size=1;
        rank=1;
        if (ch[0]!=null) {
            size+=ch[0]->size;
            rank+=ch[0]->size;
        }
        if (ch[1]!=null) size+=ch[1]->size;
        //hash maintain
        h = ch[0]->h + v*xp[rank-1] + ch[1]->h*xp[rank];
        cvh = ch[1]->cvh + v*xp[size-rank] + ch[0]->cvh*xp[size-rank+1];
    }
};

Node* null;

Node* init(int l,int r)
{
    Node* p;
    int mid=(l+r)>>1;

    p=(Node*)malloc(sizeof(Node));
    p->size = r-l+1;
    p->rank = mid-l+1;
    p->v =  mid ? str[mid-1]-'0' : 0;
    p->flip = 0;
    p->ch[0] = p->ch[1] =null;
    if (mid-1>=l) p->ch[0]=init(l,mid-1);
    if (mid+1<=r) p->ch[1]=init(mid+1,r);
    //hash init
    p->h = p->ch[0]->h + p->v*xp[p->rank-1] + p->ch[1]->h*xp[p->rank];
    p->cvh = p->ch[1]->cvh + p->v*xp[p->size-p->rank] + p->ch[0]->cvh*xp[p->size-p->rank+1];
    return p;
}

void rotate(Node* &o,int d)
{
    Node* k = o->ch[d^1];
    o->ch[d^1] = k->ch[d];
    k->ch[d] = o;
    o->maintain(null);
    k->maintain(null);
    o = k;
}

void splay(Node* &o,int k) {
    //correct
    o->pushdown(null);
    o->maintain(null);

    int d= o->cmp(k);
    if (d==1) k -= o->rank;
    if (d!=-1) {
        Node* p = o->ch[d];
        //correct
        p->pushdown(null);
        p->maintain(null);

        int d2 = p->cmp(k);
        int k2 = (d2==0 ? k : k-p->rank);
        if (d2!=-1) {
            splay(p->ch[d2],k2);
            if (d==d2) rotate(o,d^1);
            else rotate(o->ch[d], d);
        }
        rotate(o,d^1);
    }
}

void split(Node* o,int k,Node* &left,Node* &right)
{
    splay(o,k);
    left = o;
    right = o->ch[1];
    o->ch[1] = null;
    left->maintain(null);
}

Node* merge(Node* left,Node* right)
{
    splay(left, left->size);
    left->ch[1] = right;
    left->maintain(null);
    return left;
}

void dfs(Node* o) {
    o->pushdown(null);
    if (o->ch[0]!=null) dfs(o->ch[0]);
    printf("%d",o->v);
    if (o->ch[1]!=null) dfs(o->ch[1]);
}

int main()
{
    freopen("1.in","r",stdin);

    xp[0]=1;
    for (int i=1;i<=N-5;i++) xp[i]=xp[i-1]*x;

    Node* root;
    null=(Node*)malloc(sizeof(Node));
    null->h = null->cvh = null->flip = null->rank = null->size = null->v = 0;
    int L;

    int n,m,opt;
    while(scanf("%d%d",&n,&m)!=EOF) {
        scanf("%s",str);
        L=n;
        root=init(0,L);
        L++;
        int p,c,p1,p2;

        while (m--) {


            scanf("%d",&opt);
            Node *left, *mid, *right, *o;
            switch(opt){
                case 1: scanf("%d%d",&p,&c);
                        split(root,p+1,left,right);

                        Node* newp;
                        newp=(Node*)malloc(sizeof(Node));
                        newp->size = newp->rank = 1;
                        newp->flip = 0;
                        newp->ch[0] = newp->ch[1] = null;
                        newp->h = newp->cvh = newp->v = c;

                        root=merge(merge(left,newp),right);
                        L++;
                        break;
                case 2: scanf("%d",&p);

                        split(root,p,left,o);
                        split(o,1,mid,right);
                        free(mid);
                        root=merge(left,right);
                        L--;
                        break;
                case 3: scanf("%d%d",&p1,&p2);

                        split(root,p1,left,o);
                        split(o,p2-p1+1,mid,right);
                        mid->flip ^=1;
                        //correct
                        unsigned long long tmp;
                        tmp = mid->h;
                        mid->h = mid->cvh;
                        mid->cvh = tmp;

                        root = merge(merge(left,mid),right);
                        break;
                default:scanf("%d%d",&p1,&p2);

                        int P=1, Q=L-p2, MID, ans= 0;
                        unsigned long long hash, hash2;

                        while (P<=Q){
                            MID=(P+Q)>>1;

                            split(root,p1,left,o);
                            split(o,MID,mid,right);
                            //correct flip == 1
                            //hash=mid->flip ? mid->cvh : mid->h;
                            hash = mid->h;
                            root=merge(merge(left,mid),right);

                            split(root,p2,left,o);
                            split(o,MID,mid,right);
                            //correct flip == 1
                            //hash2=mid->flip ? mid->cvh : mid->h;
                            hash2 = mid->h;
                            root=merge(merge(left,mid),right);

                            if (hash==hash2) {
                                ans=MID;
                                P=MID+1;
                            }
                            else Q=MID-1;
                        }
                        printf("%d\n",ans);

                        break;
            }
            //debug
            dfs(root);
            printf("\n");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值