【bzoj 3595】: [Scoi2014]方伯伯的Oj

http://www.lydsy.com/JudgeOnline/problem.php?id=3595


终于做了一道方伯伯系列了,在我还年轻的时候,我还分不清线段树和平衡树呢、、、貌似写了个暴力骗了10分。?

几次没有改调试输出,wa率瞬间被我拉高了快哭了


这道题开始看简直没思路,双关键字的平衡树。。。。。?

后来发现这个编号简直没用,才算把题意弄清楚,随便写了treap,A了

值得注意的是细节有点多尤其是关于区间大小的计算,很容易手抖。

Orz写动态开点线段树的

Orz写fhqTreap+SBT的


//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
/************************************************
Code By willinglive    Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int getint()
{
    int r=0,k=1;char c=getchar();
    for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
    for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
    return k*r;
}
/
int n,m;
struct data{int l,r,s,rnd,index,ll,rr;}T[3000010];
int root,sz;
map<int,int>M1;
int mmin,mmax;
/
#define LS T[o].l
#define RS T[o].r
int rnd(){return rand()<<16|rand();}
void update(int o){T[o].s=T[LS].s+T[RS].s+T[o].rr-T[o].ll+1;}
void l_rot(int &o){int t=RS;RS=T[t].l;T[t].l=o;T[t].s=T[o].s;update(o);o=t;}
void r_rot(int &o){int t=LS;LS=T[t].r;T[t].r=o;T[t].s=T[o].s;update(o);o=t;}
void insert(int &o,int index,int ll,int rr)
{
	if(!o)
	{
		o=++sz; T[o].s=rr-ll+1; T[o].rnd=rnd(); T[o].index=index; T[o].ll=ll; T[o].rr=rr;
		return;
	}
	T[o].s+=rr-ll+1;
	if(ll<T[o].ll)
	{
		insert(LS,index,ll,rr);
		if(T[LS].rnd<T[o].rnd) r_rot(o);
	}
	else
	{
		insert(RS,index,ll,rr);
		if(T[RS].rnd<T[o].rnd) l_rot(o);
	}
}
void del(int &o,int pos,int sz)
{
	if(!o) return;
	if(T[o].ll==pos)
	{
		if(LS==0||RS==0) o=LS+RS;
		else if(T[LS].rnd<T[RS].rnd) r_rot(o),del(o,pos,sz);
		else l_rot(o),del(o,pos,sz);
		return;
	}
	T[o].s-=sz;
	if(pos<T[o].ll) del(LS,pos,sz);
	else 		    del(RS,pos,sz);
}
void split(int o,int pos)
{
	if(!o) return;
	if(T[o].ll<=pos && pos<=T[o].rr)
	{
		if(T[o].ll==T[o].rr) del(root,pos,1);
		else
		{
			del(root,T[o].ll,T[o].rr-T[o].ll+1);
			if(T[o].ll<=pos-1) insert(root,T[o].ll,T[o].ll,pos-1);
			if(pos+1<=T[o].rr) insert(root,pos+1,pos+1,T[o].rr);
		}
		return;
	}
	if(pos<T[o].ll) split(LS,pos);
	else			split(RS,pos);
}
int getrank(int o,int x)
{
	if(!o) return 0;
	if(T[o].ll<=x && x<=T[o].rr)
	    return T[LS].s+x-T[o].ll+1;
    if(x<T[o].ll) return getrank(LS,x);
    else		  return T[LS].s+T[o].rr-T[o].ll+1+getrank(RS,x);
}
int getindex(int o,int x)
{
	if(!o) return 0;
	if(x>T[LS].s && x<=T[LS].s+T[o].rr-T[o].ll+1)
	{
		if(T[o].ll==T[o].rr) return T[o].index;
		else return T[o].ll+x-1-T[LS].s;
	}
	if(x<=T[LS].s)
		return getindex(LS,x);
	else
	    return getindex(RS,x-T[LS].s-(T[o].rr-T[o].ll+1));
}
/
void input()
{
    n=getint(); m=getint();
}
void solve()
{
	int a=0,op,x,y;
	insert(root,1,1,n);
	mmin=0; mmax=n;
    while(m--)
    {
    	//a=0;
    	op=getint(); x=getint(); x-=a;
    	if(op==1)
    	{
    		y=getint(); y-=a;
    		int tmp=M1[x];
    		if(!tmp) tmp=x;
    		printf("%d\n",a=getrank(root,tmp));
    		M1[y]=tmp;
    		M1[x]=0;
    		split(root,tmp);
    		insert(root,y,tmp,tmp);
    	}
    	else if(op==2)
    	{
    		int tmp=M1[x];
    		if(!tmp) tmp=x;
    		printf("%d\n",a=getrank(root,tmp));
    		split(root,tmp);
    		tmp=--mmin; M1[x]=tmp;
    		insert(root,x,tmp,tmp);
    	}
    	else if(op==3)
    	{
    		int tmp=M1[x];
    		if(!tmp) tmp=x;
    		printf("%d\n",a=getrank(root,tmp));
    		split(root,tmp);
    		tmp=++mmax; M1[x]=tmp;
    		insert(root,x,tmp,tmp);
    	}
    	else
    	{
    		printf("%d\n",a=getindex(root,x));
    	}
    }
}
/
int main()
{
    #ifndef _TEST
    freopen("std.in","r",stdin); freopen("std.out","w",stdout);
    #endif
    input(),
    solve();
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值