[AH2017/HNOI2017]单旋,洛谷P3721,模拟+维护

正题

      还挺有意思.

      手玩一下很容易就可以发现当一个最值spaly的时候只会更改O(1)个节点的关系,并且子树的深度不变,其余深度+1.

      一直卡在怎么插入,看题解发现相当于在前驱和后继里面找一个深度最大的,这个很容易证明,首先前驱后继一定是当前点的祖先,因为这个点没有儿子,所以拍扁的时候前驱就是向上走第一个左父亲,后继就是第一个右父亲,深度谁大当然就谁当父亲了.

      然后要维护深度的区间加,单点更改,单点查询,直接树状数组就可以.

总结

       这玩意性质难找,但找到显然.

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;

const int N=100010;
#define pii pair<int ,int>
struct ques{
	int type,x;
}q[N];
struct node{
	int ls,rs,fa;
}s[N];
pii a[N];
int n,m,num[N],X,rt,tot;
long long sum[N],dep,pre;
set<int> S;
set<int>::iterator it;

bool cmp(const pii&a,const pii&b){return a.first<b.first;}
void add(int x,long long t){for(int i=x;i<=n;i+=lowbit(i)) sum[i]+=t;}
long long gs(int x){long long tot=0;for(int i=x;i;i-=lowbit(i)) tot+=sum[i];return tot;}
void sn(int x,int t){pre=gs(x);add(x,t-pre);add(x+1,pre-t);}

void ins(int x){
	s[x].ls=s[x].rs=s[x].fa=0;
	if(rt==0) rt=x,dep=1;
	else{ 
		it=S.lower_bound(x);
		if(it!=S.end() && !s[*it].ls) s[X=*it].ls=x;
		else it--,s[X=*it].rs=x;
		s[x].fa=X;dep=gs(X)+1;
	}
	S.insert(x);sn(x,dep);
}

void zig(){
	it=S.begin();X=*it;dep=gs(X);
	if(X!=rt) {
		add(1,1);
		if(X+1<=s[X].fa-1) add(X+1,-1),add(s[X].fa,1);
		sn(X,1);s[s[X].fa].ls=s[X].rs;s[s[X].rs].fa=s[X].fa;
		s[rt].fa=X;s[X].rs=rt;rt=X;s[X].fa=0;
	}
}

void zag(){
	it=S.end();it--;X=*it;dep=gs(X);
	if(X!=rt){
		add(1,1);
		if(s[X].fa+1<=X-1) add(s[X].fa+1,-1),add(X,1);
		sn(X,1);s[s[X].fa].rs=s[X].ls;s[s[X].ls].fa=s[X].fa;
		s[rt].fa=X;s[X].ls=rt;rt=X;s[X].fa=0;
	}
}

void zig_(){
	zig();add(1,-1);
	it=S.begin();S.erase(it);
	s[rt=s[rt].rs].fa=0;
}

void zag_(){
	zag();add(1,-1);
	it=S.end();it--;S.erase(it);
	s[rt=s[rt].ls].fa=0;
}

int main(){
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		scanf("%d",&q[i].type);
		if(q[i].type==1) scanf("%d",&q[i].x),a[++n].first=q[i].x,a[n].second=i;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++) q[a[i].second].x=i;
	for(int i=1;i<=m;i++){
		if(q[i].type==1) ins(q[i].x);
		if(q[i].type==2) zig();
		if(q[i].type==3) zag();
		if(q[i].type==4) zig_();
		if(q[i].type==5) zag_();
		printf("%lld\n",dep);
	}
}

猜你喜欢

转载自blog.csdn.net/Deep_Kevin/article/details/108351170
今日推荐