uva11922splay

Posted walfy

tags:

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

题意:一个值1到n的数组,一种(多次)操作把l到r的区间反转,然后放到数组尾部

题解:裸的splay,用区间合并和区间分割,反转用lazy标记+pushdown就好了

技术分享
#include<bits/stdc++.h>
#include<ext/rope>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;
using namespace __gnu_cxx;

const double g=10.0,eps=1e-7;
const int N=100000+10,maxn=1000000+10,inf=0x3f3f3f;

struct Node{
    Node* ch[2];
    int v;
    int s;
    int flip;
    int cmp(int x)const{
        int d = x - ch[0]->s;
        if(d==1)return -1;
        return d<=0 ? 0:1;
    }
    void maintain()
    {
        s = 1 + ch[0]->s + ch[1]->s;
    }
    void pushdown()
    {
        if(flip)//类似于线段树的lazy标记
        {
            flip=0;
            swap(ch[0],ch[1]);
            ch[0]->flip = !(ch[0]->flip);
            ch[1]->flip = !(ch[1]->flip);
        }
    }
};
Node* null = new Node();
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);//把排名最大的数splay到根
    left->ch[1] = right;
    left->maintain();
    return left;
}
void split(Node* o,int k,Node* &left,Node* &right)
{
    splay(o,k);//把排名为k的节点splay到根,右侧子树所有节点排名比k大,左侧小
    right = o->ch[1];
    o->ch[1] = null;
    left = o;
    left->maintain();
}
struct SplayTree{
    int n;
    Node seq[N];
    Node* root;
    Node* build(int sz)
    {
        if(sz==0)return null;
        Node* l=build(sz/2);
        Node* o=&seq[++n];
        o->v=n;
        o->ch[0]=l;
        o->ch[1]=build(sz-sz/2-1);
        o->s = o->flip = 0;
        o->maintain();
        return o;
    }
    void init(int sz)
    {
        n=0;
        null->s = 0;
        root = build(sz);
    }
};
vector<int>ans;
void print(Node* o)
{
    if(o!=null)
    {
        o->pushdown();
        print(o->ch[0]);
        ans.pb(o->v);
        print(o->ch[1]);
    }
}
void debug(Node* o)
{
    if(o!=null)
    {
        o->pushdown();
        debug(o->ch[0]);
        cout<<o->v<<endl;
        debug(o->ch[1]);
    }
}
SplayTree ss;
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    ss.init(n+1);
  //  debug(ss.root);
    while(m--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        Node *o,*left,*mid,*right;
        split(ss.root,a,left,o);//把ab整体右移一位,保证不会出现0
        split(o,b-a+1,mid,right);
        mid->flip^=1;
        //把left+mid+right变成left+right+mid(fliped)
        ss.root = Merge(Merge(left,right),mid);
    }
    print(ss.root);
    for(int i=1;i<ans.size();i++)
        printf("%d\n",ans[i]-1);
    return 0;
}
/************

************/
View Code

 

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

UVa 11922 & splay的合并与分裂

UVA 11922 Permutation Transformer —— splay伸展树

Uva 11922 Permutation Transformer

Splay

UVA11922 Permutation Transformer

UVA - 11922 区间反转+拼接 可持久化Treap