题目
题解
这题我写了一上午+调了一下午
日啊。。这是道模板题啊,而且我还不是自己想出来的。。GG。
hnoi的题告诉了我我有多菜。sdoi还让我有点自信,,看到hnoi一道不会但是大家都说d1好简单能AK呀。
手动再见。
我们来说说这道题吧。
单旋最大值最小值的话,可以拿手模拟几棵树然后会发现树的形态变化极其微小。拿单旋最小值来说,设这个点叫u,如果u有右儿子,那么这个右儿子会变成u父亲的左儿子。然后根会变成u的右儿子。(u就是根的情况需要另外特判。)
然后怎么做第一个操作呢。发现插入一个数的时候,要么和它前驱是父子关系要么和它后继是父子关系。(可以通过中序遍历有序来说明)。然后前驱后继在原来的树中也是父子关系。要么是前驱是后继的左儿子,要么后继是前驱的右儿子。所以就能确定,这两个位置,前驱的右儿子,后继的左儿子,哪个为空插哪里(有且仅有一个会为空)。然后就lct大力乱搞就好了。
关于怎么定位左右儿子以及原树的父亲。。我比较弱智。另外用了一个树来专门维护这个形态。。(反正变化极其微小嘛)。qwq大神们有没有什么好的方法。
(调试到昏厥)
//QWsin
#include<map>
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100000+10;
int root;//记录在spaly上的根节点的值
//map<int,int>id;
//inline void output();
namespace lct{
struct Node{
int rev,sz;
Node *ch[2],*fa;
Node(){rev=0;sz=1;ch[0]=ch[1]=fa=NULL;}
inline void up(){
sz=1;
if(ch[0]) sz+=ch[0]->sz;
if(ch[1]) sz+=ch[1]->sz;
}
inline void push()
{
if(rev){
swap(ch[0],ch[1]);
if(ch[0]) ch[0]->rev^=1;
if(ch[1]) ch[1]->rev^=1;
rev=0;
}
}
};
Node *node[maxn],*tmp[maxn];
inline void init(int n){
for(int i=1;i<=n;++i) node[i]=new Node();
}
inline int pd(Node* p){return p->fa->ch[1]==p;}
inline int is_root(Node* p){
return !(p->fa)|| (p->fa->ch[0]!=p&&p->fa->ch[1]!=p);
}
inline void rotate(Node* p)
{
int c=pd(p)^1;Node* t=p->fa;
t->ch[c^1]=p->ch[c];
if(p->ch[c]) p->ch[c]->fa=t;
p->fa=t->fa;
if(!is_root(t)) p->fa->ch[pd(t)]=p;
t->fa=p;p->ch[c]=t;t->up();p->up();
}
inline void splay(Node* p)
{
int top=0;
for(Node*t=p;;t=t->fa)
{
tmp[++top]=t;
// if(top>maxn) {int t=1/0;}
if(is_root(t)) break;
}
for(;top>=1;--top) tmp[top]->push();
// output();
for(;!is_root(p);rotate(p))
if(!is_root(p->fa)) rotate(pd(p)==pd(p->fa) ? p->fa:p);
}
inline void access(Node* p){
for(Node* pre=NULL;p;pre=p,p=p->fa)
{
splay(p),p->ch[1]=pre,p->up();
// output();
}
}
inline void make_root(Node* p){
access(p);
// output();
splay(p);
// output();
p->rev=1;
}
inline void link(Node* a,Node *b){
make_root(a);
a->fa=b;
}
inline void cut(Node* a,Node *b){
make_root(a);
// output();
access(b);
// output();
splay(b);
// output();
b->ch[0]=a->fa=NULL;b->up();
}
inline int getdeep(Node* p){
make_root(node[root]);
// output();
access(p);
// output();
splay(p);
// output();
int t=p->ch[0]?p->ch[0]->sz:0;
return t+1;
}
inline void make_root(int x){make_root(node[x]);}
inline void link(int a,int b){link(node[a],node[b]);}
inline void cut (int a,int b){cut (node[a],node[b]);}
inline int getdeep(int x){return getdeep(node[x]);}
}
//inline void output(){
//
// for(int i=1;i<=5;++i)
// {
// printf("node[%d]:\n",i);
// printf(" sz=%d\n",lct::node[i]->sz);
// printf(" ch[0]=%d\n",id[(int)lct::node[i]->ch[0]]);
// printf(" ch[1]=%d\n",id[(int)lct::node[i]->ch[1]]);
// printf(" fa=%d\n",id[(int)lct::node[i]->fa]);
// puts("");
// }
// puts("");
//}
int tmp[maxn],tmp_p;
struct OP{
int k,a;
OP(int a=0,int b=0):k(a),a(b){}
inline void input(){
scanf("%d",&k);
if(k==1) {
scanf("%d",&a);
tmp[++tmp_p]=a;
}
}
}op[maxn];
int m;
inline void init_data()
{
cin>>m;lct::init(m);
for(int i=1;i<=m;++i) op[i].input();
sort(tmp+1,tmp+tmp_p+1);
int cc=unique(tmp+1,tmp+tmp_p+1)-tmp-1;
for(int i=1;i<=m;++i) if(op[i].k==1){
op[i].a=lower_bound(tmp+1,tmp+cc+1,op[i].a)-tmp;
}
}
set<int>st;
set<int>::iterator it;
struct Node{
int val;
Node *fa,*ch[2];
Node(int val):val(val){fa=ch[0]=ch[1]=NULL;}
inline void clear(){fa=ch[0]=ch[1]=NULL;}
}*node[maxn];
//操作1(val需要离散)
inline void insert(int val)
{
it=st.insert(val).first;
node[val]=new Node(val);
if(st.size()!=1)
{
int done=0;
if(it!=st.begin())
{
--it;
if(node[*it]->ch[1]==NULL)
{
node[*it]->ch[1]=node[val];done=1;
node[val]->fa=node[*it];
lct::link(*it,val);
// output();
printf("%d\n",lct::getdeep(val));
}
++it;
}
if(!done) {
node[*(++it)]->ch[0]=node[val];
node[val]->fa=node[*it];
lct::link(*it,val);
printf("%d\n",lct::getdeep(val));
}
}
else root=val,puts("1");
}
#define rc node[*it]->ch[1]
#define lc node[*it]->ch[0]
#define Fa node[*it]->fa
inline void RotMin(int del)
{
it=st.begin();
printf("%d\n",lct::getdeep(*it));
// output();
// cout<<*it<<endl;
if(*it==root)
{
if(!del) return ;
if(rc){
lct::cut(*it,rc->val);
rc->fa=NULL;
root=rc->val;
}
st.erase(*it);return ;
}
lct::cut(*it,Fa->val);
// output();
Fa->ch[0]=rc;
if(rc)
{
lct::cut(*it,rc->val);
rc->fa=Fa;
lct::link(rc->val,Fa->val);
}
// cout<<"*it="<<*it<<endl;
if(!del)
{
node[*it]->clear();
rc=node[root];
node[root]->fa=node[*it];
lct::link(*it,root);
// output();
root=*it;
}
else st.erase(*it);
}
inline void RotMax(int del)
{
it=--(st.end());
printf("%d\n",lct::getdeep(*it));
if(*it==root)
{
if(!del) return ;
if(lc){
lct::cut(*it,lc->val);
lc->fa=NULL;
root=lc->val;
}
st.erase(*it);return ;
}
// cout<<"*it="<<*it<<endl;
lct::cut(Fa->val,*it);
Fa->ch[1]=lc;
if(lc)
{
lc->fa=Fa;
lct::cut(*it,lc->val);
lct::link(Fa->val,lc->val);
}
if(!del)
{
node[*it]->clear();
lc=node[root];
node[root]->fa=node[*it];
lct::link(root,*it);
root=*it;
}
else st.erase(*it);
}
inline void solve()
{
// id[0]=0;
// for(int i=1;i<=m;++i) id[(int)lct::node[i]]=i;
for(int i=1;i<=m;++i)
{
// printf("id= %d\n",i);
// output();
// if(op[i].k==2) {
// int stop=1;
// }
if(op[i].k==1) insert(op[i].a);
else if(op[i].k==2) RotMin(0);
else if(op[i].k==3) RotMax(0);
else if(op[i].k==4) RotMin(1);
else if(op[i].k==5) RotMax(1);
}
}
int main()
{
init_data();
solve();
return 0;
}