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;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#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 = 200005;
struct node{
    int ch[2],fa,val,sz,cnt,sd;
    bool rev;
    void init(int x,int ff,int y)
    {
        ch[0]=ch[1]=rev=0;sd=y;
        cnt=sz=1;val=x;fa=ff;
    }
}tr[N+1];
P b[N];
stack<int>st;
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;
    int 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)//伸展
{
    for(int qw=x;qw!=goal;qw=tr[qw].fa) st.push(qw);
    while(!st.empty())  pushdown(st.top()),st.pop();
    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 y)//加点
{
    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,y);
    }
    splay(cur);
}
void rever(int x)//区间翻转
{
    splay(x);
    tr[tr[x].ch[0]].rev^=1;
}
void remov()//删点
{
    int z=tr[root].ch[0];
    if(!z)
    {
        root=tr[root].ch[1];
        tr[root].fa=0;
        return;
    }
    while(233)
    {
        pushdown(z);
        if(!tr[z].ch[1]) break;
        z=tr[z].ch[1];
    }
    splay(z,root);
    tr[z].ch[1]=tr[root].ch[1];
    tr[tr[root].ch[1]].fa=z;
    root=z,tr[z].fa=0;
    pushup(z);
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    while(si(n)!=EOF&&n)
    {
        root=ncnt=tr[0].ch[0]=tr[0].ch[1]=tr[0].cnt=tr[0].fa=tr[0].rev=tr[0].sd=tr[0].sz=tr[0].val=0;
        add(inf,0);
        FOR(i,1,n) si(x),add(i,x),b[i].first=x,b[i].second=i;
        sort(b+1,b+n+1);
        FOR(i,1,n)
        {
            x=b[i].second;
            rever(x+1);
            if(i!=n) printf("%d ",i+tr[tr[root].ch[0]].sz);
            else printf("%d\n",i+tr[tr[root].ch[0]].sz);
            remov();
        }
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值