splay(luoguP3391)

題目鏈接:https://www.luogu.org/problem/P3391

思路:splay模板題

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <unordered_map>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define pb push_back
#define eps 1e-7
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
const int N = 100005;
struct node{
    int ch[2],fa,val,sz,cnt;
    bool rev;
    void init(int x,int ff)
    {
        ch[0]=ch[1]=0;
        cnt=sz=1;val=x;fa=ff;
    }
}tr[N+1];
int root,ncnt;
int n,m,x,y;
bool chk(int x) {return tr[tr[x].fa].ch[1]==x;}
void pushup(int x) {tr[x].sz=tr[tr[x].ch[0]].sz+tr[tr[x].ch[1]].sz+tr[x].cnt;}
void pushdown(int x)//標記
{
    if(tr[x].rev)
    {
        swap(tr[x].ch[0],tr[x].ch[1]);
        tr[tr[x].ch[0]].rev^=1;
        tr[tr[x].ch[1]].rev^=1;
        tr[x].rev=0;
    }
}
void rot(int x)//旋轉
{
    int y=tr[x].fa,z=tr[y].fa,k=chk(x),w=tr[x].ch[k^1];
    tr[y].ch[k]=w;tr[w].fa=y;
    tr[z].ch[chk(y)]=x;tr[x].fa=z;
    tr[x].ch[k^1]=y;tr[y].fa=x;
    pushup(y);pushup(x);
}
void splay(int x, int goal = 0)//伸展
{
    while(tr[x].fa!=goal)
    {
        int y=tr[x].fa,z=tr[y].fa;
        if(z!=goal)
         chk(x)^chk(y)?rot(x):rot(y);
        rot(x);
    }
    if(!goal) root=x;
}
void add(int x)//加點
{
    int cur=root,p=0;
    while(cur&&tr[cur].val!=x)
    {
        p=cur;
        cur=tr[cur].ch[x>tr[cur].val];
    }
    if(cur) tr[cur].cnt++;
    else
    {
        cur=++ncnt;
        if(p) tr[p].ch[x>tr[p].val]=cur;
        tr[cur].init(x,p);
    }
    splay(cur);
}
void fid(int x)
{
    int cur=root;
    while(tr[cur].ch[x>tr[cur].val]&&tr[cur].val!=x)
     cur=tr[cur].ch[x>tr[cur].val];
    splay(cur);
}
int kth(int k)//第幾大
{
    int cur=root;
    while(666)
    {
        pushdown(cur);
        if(tr[cur].ch[0]&&k<=tr[tr[cur].ch[0]].sz) cur=tr[cur].ch[0];
        else if(k>tr[tr[cur].ch[0]].sz+tr[cur].cnt)
        {
            k-=tr[tr[cur].ch[0]].sz+tr[cur].cnt;
            cur=tr[cur].ch[1];
        }
        else return cur;
    }
}
void rever(int l,int r)//區間翻轉
{
    int x=kth(l),y=kth(r+2);
    splay(x); splay(y,x);
    tr[tr[y].ch[0]].rev^=1;
}
int pre(int x)//前驅
{
    fid(x);
    if(tr[root].val<x) return root;
    int cur=tr[root].ch[0];
    while(tr[cur].ch[1]) cur=tr[cur].ch[1];
    return cur;
}
int succ(int x)//後繼
{
    fid(x);
    if(tr[root].val>x) return root;
    int cur=tr[root].ch[1];
    while(tr[cur].ch[0]) cur=tr[cur].ch[0];
    return cur;
}
void remov(int x)//刪點
{
    int last=pre(x),next=succ(x);
    splay(last);splay(next,last);
    int del=tr[next].ch[0];
    if(tr[del].cnt>1) tr[del].cnt--,splay(del);
    else tr[next].ch[0]=0;
    pushup(next),pushup(root);
}
void output(int x)//輸出遍歷
{
    pushdown(x);
    if(tr[x].ch[0]) output(tr[x].ch[0]);
    if(tr[x].val&&tr[x].val<=n) printf("%d ",tr[x].val);
    if(tr[x].ch[1]) output(tr[x].ch[1]);
}
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    FOR(i,0,n+1) add(i);
    while(m--)
    {
        x=read(),y=read();
        rever(x,y);
    }
    output(root);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章