BZOJ3678 wangxz与OJ

由于题面包含不良信息,因此这里只放传送门。

题目大意:

维护一个序列,支持:

1、区间删除

2、在一个位置插入一段递增或递减的连续的数

3、单点查询

 

$splay$拆点,一个节点表示段连续的区间,必要时将一个点分裂成两个点。

空间一定是线性的,思维含量并不高,但是细节一堆。

很裸吧......

你写吧......

我们强无敌的$wxjor$巨佬以$6KB$代码$47pt$收场。

俗话说得好

有些人还活着,但它们的代码已经调不出来了。

有些人已经死了,但它们的代码还没有调出来。

只要写不死,就往死里写。 

$Orz$模拟赛里$Ac$的神爷们

 

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define M 600020
#define ls c[x][0]
#define rs c[x][1]
using namespace std;
int read(){
	int nm=0,fh=1; char cw=getchar();
	for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
	for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
	return nm*fh;
}
int tpe,n,m,T,c[M][2],cnt,rt,fa[M],L[M],R[M],sum[M],X,Y;
void pushup(int x){sum[x]=sum[ls]+sum[rs]+abs(R[x]-L[x])+1;}
void rotate(int x){
	int tp=fa[x],dtp=fa[fa[x]],ms,ds;
	if(dtp&&c[dtp][0]==tp) c[dtp][0]=x; else if(dtp) c[dtp][1]=x;
	if(c[tp][0]==x) ms=0,ds=1;else ds=0,ms=1;
	fa[x]=dtp,fa[tp]=x,fa[c[x][ds]]=tp;
	c[tp][ms]=c[x][ds],c[x][ds]=tp,pushup(tp),pushup(x);
}
void splay(int x,int tar){
	while(fa[x]!=tar){
		int tp=fa[x];
		if(fa[tp]==tar){rotate(x);break;}
		if(c[c[fa[tp]][0]][0]==x) rotate(tp);
		else if(c[c[fa[tp]][1]][1]==x) rotate(tp);
		else rotate(x);
	}
	if(!tar) rt=x;
}
int fd(int x,int rk){
	if(sum[ls]>=rk) return fd(ls,rk);
	if(sum[x]-sum[rs]>=rk) return x;
	return fd(rs,rk-sum[x]+sum[rs]);
}
int mn(int x){for(;ls;x=ls); return x;}
int query(int pos){
	int x=fd(rt,pos),dt,rm; splay(x,0);
	dt=(R[x]>=L[x]?1:-1),rm=pos-sum[ls]-1;
	return L[x]+rm*dt;
}
void ins(int pos,int t1,int t2){
	int x=++cnt,u; L[x]=t1,R[x]=t2,pushup(x);
	if(!rt){rt=x; return;}
	if(!pos){rs=rt,fa[rt]=x,rt=x,pushup(x);return;}
	int now=fd(rt,pos);	splay(now,0);
	if(sum[now]-sum[c[now][1]]==pos){
		if((u=mn(c[now][1]))==0) c[now][1]=x,fa[x]=now,pushup(now);
		else splay(u,now),c[u][0]=x,fa[x]=u,pushup(u),pushup(now);
	}
	else{
		int dt=(R[now]>=L[now]?1:-1),rm=pos-sum[c[now][0]];
		cnt++,R[cnt]=R[now],L[cnt]=dt*rm+L[now],R[now]=L[cnt]-dt;
		c[cnt][1]=c[now][1],c[now][1]=0,pushup(now),pushup(cnt),fa[c[cnt][1]]=cnt;
		ls=now,rs=cnt,fa[now]=fa[cnt]=x,rt=x,fa[0]=0,pushup(x);
    }
}
void del(int t1,int t2){
	int x=fd(rt,t1),y=fd(rt,t2),u,dt; splay(x,0);
	t1-=sum[ls],splay(y,0),t2-=sum[c[y][0]];
	if(x!=y){
		splay(x,y),rs=0,pushup(x),pushup(y);
		if(t1>1) dt=(R[x]>=L[x]?1:-1),R[x]=L[x]+dt*(t1-2),pushup(x),pushup(y);
		else fa[ls]=y,fa[0]=0,c[y][0]=ls,pushup(y); x=y;
		if(t2<abs(R[x]-L[x])+1) dt=(R[x]>=L[x]?1:-1),L[x]+=dt*t2,pushup(x);
		else if((y=mn(rs))==0) rt=ls,fa[ls]=0;
		else splay(y,x),rt=y,c[y][0]=ls,fa[ls]=y,fa[y]=0,pushup(y);
    }
    else{
	    dt=(R[x]>=L[x]?1:-1);
    	if(t2-t1==abs(R[x]-L[x])){
		    if((u=mn(rs))==0) rt=ls,fa[ls]=0;
			else splay(u,x),c[u][0]=ls,fa[ls]=u,fa[u]=0,rt=u,pushup(u);
		}	
    	else if(t1==1) L[x]+=(t2-t1+1)*dt,pushup(x);
    	else if(t2==abs(R[x]-L[x])+1) R[x]-=(t2-t1+1)*dt,pushup(x);
    	else{
			if((u=mn(rs))==0) rs=++cnt,fa[cnt]=x;
			else splay(u,x),c[u][0]=++cnt,fa[cnt]=u;
			R[cnt]=R[x],R[x]=L[x]+(t1-2)*dt,L[cnt]=R[x]+(t2-t1+2)*dt;
			pushup(cnt),pushup(rs),sum[x]=0,pushup(x);
	    }
	}
}
int main(){
	n=read(),T=read();
	for(int i=1;i<=n;i++) m=read(),ins(i-1,m,m);
	while(T--){
		tpe=read(),X=read();
		if(tpe==2) printf("%d\n",query(X));
		else if(tpe==1) Y=read(),del(X,Y);
		else tpe=X, X=read(),Y=read(),ins(tpe,X,Y);
	}
	return 0;
}

 

posted @ 2018-09-11 17:54  OYJason  阅读(189)  评论(1编辑  收藏  举报