UVA 11922+11996(Splay

题目:维护一个序列,支持将一段数翻转并插到最后的操作,最后输出整个序列。

思路:直接套的大白模板,第一次用splay,贴一下。。

/*
*@author:  Cwind
*http://www.cnblogs.com/Cw-trip/
*/
#include <bits/stdc++.h>
#define pb push_back
#define PB pop_back
#define bk back()
#define se second
#define fs first
#define IINF (1<<29)
#define sq(x) (x)*(x)
#define eps 0.000000001
#define clr(x) memset((x),0,sizeof (x))
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;

const int maxp=1e6+3000;
struct Node{
    int s;
    int val;
    bool flip;
    Node *ch[2];
    Node():s(0),flip(0){}
    int cmp(const int k)const {
        int d=k-ch[0]->s;
        if(d==1) return -1;
        else return d>0;
    }
    void maintain(){
        s=ch[0]->s+ch[1]->s+1;
    }
    void pushdown(){
        if(flip){
            flip=0;
            swap(ch[0],ch[1]);
            ch[0]->flip^=1;
            ch[1]->flip^=1;
        }
    }
}pool[maxp];
Node *null=new Node();
int ph=0;
Node *newNode(){
    Node *n=&pool[ph++];
    n->flip=n->s=0;
    return n;
}
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();
    k->maintain();
    o=k;
}
void splay(Node *&o,int k){
    o->pushdown();
    int d=o->cmp(k);
    if(d==1) k-=o->ch[0]->s+1;
    if(d!=-1){
        Node *p=o->ch[d];
        p->pushdown();
        int d2=p->cmp(k);
        int k2=(d2==0?k:k-p->ch[0]->s-1);
        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);
    }
}
Node* merge(Node *left,Node *right){
    splay(left,left->s);
    left->ch[1]=right;
    left->maintain();
    return left;
}
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();
}
int num=0;
Node *build(int sz){
    if(sz==0) return null;
    Node *n=newNode();
    n->ch[0]=build(sz/2);
    n->val=num++;
    n->ch[1]=build(sz-sz/2-1);
    n->maintain();
    return n;
}
void print(Node *n){
    if(n==null) return;
    n->pushdown();
    print(n->ch[0]);
    if(n->val!=0)printf("%d\n",n->val);
    print(n->ch[1]);
}
int n,m;
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    //freopen("defense.in","r",stdin);
    //freopen("defense.out","w",stdout);
    cin>>n>>m;
    Node *root=build(n+1);
    while(m--){
        int a,b;
        scanf("%d%d",&a,&b);
        Node *l,*r,*m,*o;
        split(root,a,l,o);
        split(o,b-a+1,m,r);
        m->flip^=1;
        root=merge(merge(l,r),m);
    }
    print(root);
    return 0;
}
View Code

 11996

题目:给出一个01序列,要求支持插入,删除,查询任意后缀的lcp。

思路:splay+hash。。。但是看完之后就觉得好难写啊==,遂拖到了昨天,终于下决心填坑。。。。。本来想按着自己的想法写的,结果写完之后连hash值都搞不对。。。。今天果断重写,,继续gg。。。。然后参考例程写了一遍,感觉还是学了几个很重要的技巧的,比如提取一个子串,以及添加一个子串或字符。如果不学习例程的话,我是准备用分裂合并搞的,那样的话效率和写法都很难看。。。。

/*
* @author:  Cwind
*/
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define bk back()
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps (1e-3)
#define IINF (1<<29)
#define LINF (1ll<<59)
#define INF 1000000000
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;


const int maxp=1e6+3000;
const int maxn=2e5+300;
int J[maxn];
ull shift[maxn];
ull HV=3137;
struct Node *root;
int n,m;
struct Node{
    int s;
    int val;
    int id;
    bool flip;
    ull h1,h2;
    Node *ch[2];
    Node():s(0),flip(0),h1(0),h2(0){}
    int cmp(const int k)const {
        int d=k-ch[0]->s;
        if(d==1) return -1;
        else return d>0;
    }
    void maintain(){
        s=ch[0]->s+ch[1]->s+1;
        h1=ch[0]->h1+val*shift[ch[0]->s]+ch[1]->h1*shift[ch[0]->s+1];
        h2=ch[1]->h2+val*shift[ch[1]->s]+ch[0]->h2*shift[ch[1]->s+1];
    }
    void reverse(){
        flip^=1;
        swap(ch[0],ch[1]);
        swap(h1,h2);
    }
    void pushdown(){
        if(flip){
            flip=0;
            ch[0]->reverse();
            ch[1]->reverse();
        }
    }
}pool[maxp];
Node *null=new Node();
int ph=0;
Node *newNode(int val=0){
    Node *n=&pool[ph++];
    n->flip=0;
    n->s=1;
    n->val=n->h1=n->h2=val;
    n->ch[1]=n->ch[0]=null;
    return n;
}
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();
    k->maintain();
    o=k;
}
void splay(Node *&o,int k){
    o->pushdown();
    int d=o->cmp(k);
    if(d==1) k-=o->ch[0]->s+1;
    if(d!=-1){
        Node *p=o->ch[d];
        p->pushdown();
        int d2=p->cmp(k);
        int k2=(d2==0?k:k-p->ch[0]->s-1);
        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);
    }
}

Node *&getRange(int p1,int p2){
    splay(root,p1);
    splay(root->ch[1],p2-p1+1);
    return root->ch[1]->ch[0];
}
Node *getLast(){
    return root->ch[1]->ch[0]; 
}
int num=0;
int id=0;
Node *build(int sz){
    if(sz==0) return null;
    Node *n=newNode();
    n->ch[0]=build(sz/2);
    n->id=id++;
    n->val=J[num++];
    n->ch[1]=build(sz-sz/2-1);
    n->maintain();
    return n;
}
void update(){
    root->ch[1]->maintain();
    root->maintain();
}
void print(Node *n){
    if(n==null) return;
    n->pushdown();
    print(n->ch[0]);
    printf("%d %d\n",n->val,n->id);
    print(n->ch[1]);
}
void init(){
    shift[0]=1;
    for(int i=1;i<maxn;i++){
        shift[i]=shift[i-1]*HV;
    }
}

char r[maxn];
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    //freopen("defense.in","r",stdin);
    //freopen("defense.out","w",stdout);
    init();
    while(cin>>n>>m){
        ph=0,num=0,id=0;
        scanf("%s",r);
        for(int i=1;i<=n;i++){
            J[i]=r[i-1]-'0';
        }
        J[n+1]=0;
        root=build(n+2);
        while(m--){
            int Q;
            scanf("%d",&Q);
            if(Q==1){
                int p,c;
                scanf("%d%d",&p,&c);
                p++;
                getRange(p,p)=newNode(c);
                update();
            }else if(Q==2){
                int p;
                scanf("%d",&p);
                getRange(p,p+1)=null;
                update();
            }else if(Q==3){
                int p1,p2;
                scanf("%d%d",&p1,&p2);
                getRange(p1,p2+1)->reverse();
                update();
            }else{
                int p1,p2;
                scanf("%d%d",&p1,&p2);
                int l=0,r=root->s-p2;
                while(r-l>1){
                    int mid=(r+l)/2;
                    ull h1=getRange(p1,p1+mid)->h1;
                    ull h2=getLast()->h2;
                    h1-=getRange(p2,p2+mid)->h1;
                    h2-=getLast()->h2;
                    if(!h1&&!h2){
                        l=mid;
                    }else{
                        r=mid;
                    }
                }
                printf("%d\n",l);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2015-09-06 15:51  PlusSeven  阅读(197)  评论(0编辑  收藏  举报