splay专题

splay是个很好的东西,与线段树相比,它能够实现诸如将区间翻转等操作,而复杂度也是平均logn的
splay的复杂度优秀在于它是一棵二叉树,而一个节点又代表了一个区间,那么寻找一个区间[l,r]并修改或是询问它,利用二叉树的性质,只需要将l-1旋转至根,r+1旋转至根的左儿子处,那么根的左儿子的右儿子就代表了要修改的区间了,而因为它是一棵"平衡"二叉树,所以复杂度还是有保证的。
splay例题:
裸题(写前面几道时自己手还挺生的,模板不是很好):
bzoj1503
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int N=100050;
struct node
{
	int l,r,f,s,v,num;
}tree[N];
int n,m,l,cnt,root,del;
void pushup(int x)
{
	tree[x].s=tree[tree[x].l].s+tree[tree[x].r].s+1;
}
void zig(int &x)
{
	int fa=tree[x].f;
	int grfa=tree[fa].f;
	if(fa==tree[grfa].l)
		tree[grfa].l=x;
	else
		tree[grfa].r=x;
	tree[x].f=grfa;
	tree[fa].l=tree[x].r;
	tree[tree[x].r].f=fa;
	tree[x].r=fa;
	tree[fa].f=x;
	pushup(fa);
	pushup(x);
	if(fa==root)
		root=x;
}
void zag(int &x)
{
	int fa=tree[x].f;
	int grfa=tree[fa].f;
	if(fa==tree[grfa].l)
		tree[grfa].l=x;
	else
		tree[grfa].r=x;
	tree[x].f=grfa;
	tree[fa].r=tree[x].l;
	tree[tree[x].l].f=fa;
	tree[x].l=fa;
	tree[fa].f=x;
	pushup(fa);
	pushup(x);
	if(fa==root)
		root=x;
}
void splay(int &x,int d)
{
	while(tree[x].f!=d)
	{
		if(tree[tree[x].f].l==x)
			zig(x);
		else 
			zag(x);
	}
}
void insert(int k)
{
	if(!root)
	{
		root=++cnt;
		tree[cnt].num=k;
		tree[cnt].s=1;
		return ;
	}
	int p=root,z;
	while(p)
	{
		z=p;
		++tree[p].s;
		if(k<tree[p].num)
			p=tree[p].l;
		else
			p=tree[p].r;
	}
	if(tree[z].num>k)
		tree[z].l=++cnt;
	else
		tree[z].r=++cnt;
	tree[cnt].num=k;
	tree[cnt].s=1;
	tree[cnt].f=z;
	splay(cnt,0);
}
int find(int x,int k)
{
	if(k<=tree[tree[x].r].s)
	{
		return find(tree[x].r,k);
}
	if(k==tree[tree[x].r].s+1)
		return tree[x].num;
		
	return find(tree[x].l,k-tree[tree[x].r].s-1);
}
int dec(int &x,int f)
{
	if(!x) return 0;
	int k;
	if(tree[x].num+del<m)
	{
		k=dec(tree[x].r,x)+tree[tree[x].l].s+1;
		tree[tree[x].r].s=tree[x].s-k;
		x=tree[x].r;
		tree[x].f=f;
	}
	else
	{
		k=dec(tree[x].l,x);
		tree[x].s-=k;
	}
	return k;
}
int main()
{
	scanf("%d%d",&n,&m);
	while(n--)
	{
		char c[1];
		int k;
		scanf("%s%d",&c,&k);
		if(c[0]=='I'&&k>=m)
			insert(k-del);
		if(c[0]=='F')
			printf("%d\n",k<=tree[root].s?find(root,k)+del:-1);
		if(c[0]=='A')
			del+=k;
		if(c[0]=='S')
		{
			del-=k;
			l+=dec(root,0);
		}
	}
	printf("%d\n",l);

	
}

bzoj1251
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#define lson tree[x].l 
#define rson tree[x].r 
using namespace std;
const int inf=0x3f3f3f3f;
const int N=100050;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
struct node
{
	int l,r,f,s,rev,mx,num,tag;
}tree[N];
int n,m,l,cnt,root,del,id[N];
void pushup(int x)
{
	tree[x].s=tree[lson].s+tree[rson].s+1;
	tree[x].mx=max(tree[lson].mx,tree[rson].mx);
	tree[x].mx=max(tree[x].mx,tree[x].num);
}
void pushdown(int x)
{
	int l=tree[x].l,r=tree[x].r,t=tree[x].tag;
	if(t)
	{
		tree[x].tag=0;
		if(l)
		{
			tree[l].tag+=t;
			tree[l].mx+=t;
			tree[l].num+=t; 
		}
		if(r)
		{
			tree[r].tag+=t;
			tree[r].mx+=t;
			tree[r].num+=t;
		}
	}
	if(tree[x].rev)
	{
		tree[x].rev=0;
		tree[l].rev^=1;
		tree[r].rev^=1;
		swap(tree[x].l,tree[x].r);
	}
}
void zig(int &x)
{
	int fa=tree[x].f;
	int grfa=tree[fa].f;
	if(fa==tree[grfa].l)
		tree[grfa].l=x;
	else
		tree[grfa].r=x;
	tree[x].f=grfa;
	tree[fa].l=tree[x].r;
	tree[tree[x].r].f=fa;
	tree[x].r=fa;
	tree[fa].f=x;
	pushup(fa);
	pushup(x);
	if(fa==root)
		root=x;
}
void zag(int &x)
{
	int fa=tree[x].f;
	int grfa=tree[fa].f;
	if(fa==tree[grfa].l)
		tree[grfa].l=x;
	else
		tree[grfa].r=x;
	tree[x].f=grfa;
	tree[fa].r=tree[x].l;
	tree[tree[x].l].f=fa;
	tree[x].l=fa;
	tree[fa].f=x;
	pushup(fa);
	pushup(x);
	if(fa==root)
		root=x;
}
void splay(int &x,int d)
{
	while(tree[x].f!=d)
	{
		//cout<<x<<" "<<tree[x].f<<" "<<d<<endl;
		if(tree[tree[x].f].l==x)
			zig(x);
		else
			zag(x);
	}
}
int find(int x,int k)
{
	if(tree[x].tag||tree[x].rev)
		pushdown(x);
	if(k<=tree[tree[x].l].s)
		return find(tree[x].l,k);
	if(k==tree[tree[x].l].s+1)
		return x;
	return find(tree[x].r,k-tree[tree[x].l].s-1);
}
inline void update(int l,int r,int v)
{
	int x=find(root,l),y=find(root,r+2);
	splay(x,0);
	splay(y,x);
	int z=tree[y].l;
	tree[z].tag+=v;
	tree[z].num+=v;
	tree[z].mx+=v;
}
inline void rever(int l,int r)
{
	int x=find(root,l);
	int y=find(root,r+2);
	splay(x,0);
	splay(y,x);
	int z=tree[y].l;
	tree[z].rev^=1;
}
inline void query(int l,int r)
{
	int x=find(root,l);
	int y=find(root,r+2);
	splay(x,0);
	splay(y,x);
	int z=tree[y].l;
	printf("%d\n",tree[z].mx);
}
inline void build(int l,int r,int f)
{
	if(l>r)
		return ;
	int now=id[l],last=id[f];
	if(l==r)
	{
		tree[now].f=last;
		tree[now].s=1;
		if(l<f)
			tree[last].l=now;
		else
			tree[last].r=now;
		return ;
	} 
	int mid=(l+r)/2;
	now=id[mid];
	build(l,mid-1,mid);
	build(mid+1,r,mid);
	tree[now].f=last;
	pushup(now);
	if(mid<f)
		tree[last].l=now;
	else
		tree[last].r=now;
}
int sz=0;
int main()
{
	tree[0].mx=-inf;
	n=read();
	m=read();
	for(int i=1;i<=n+2;i++)
		id[i]=i;
	build(1,n+2,0);
	root=(n+3)/2;
	for(int i=1;i<=m;i++)
	{
		int f=read(),l,r,val;
		switch(f)
		{
		case 1:l=read();r=read();val=read();update(l,r,val);break;
		case 2:l=read();r=read();rever(l,r);break;
		case 3:l=read();r=read();query(l,r);break;
		}
	}
	return 0;
}

bzoj3223
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
using namespace std;
const int N=100050;
struct node
{
	int l,r,rev,f,s;
}tree[N];
void pushup(int x)
{
	tree[x].s=tree[tree[x].l].s+tree[tree[x].r].s+1;
}
int a,b,n,m,id[N],root;
void pushdown(int x)
{
	if(tree[x].rev)
	{
		tree[x].rev=0;
		tree[tree[x].l].rev^=1;
		tree[tree[x].r].rev^=1;
		swap(tree[x].l,tree[x].r);
	}
}
void build(int l,int r,int f)
{
	if(l>r)
		return ;
	int now=id[l],last=id[f];
	if(l==r)
	{
		tree[now].f=last;
		tree[now].s=1;
		if(l<f)
			tree[last].l=now;
		else
			tree[last].r=now;
		return ;
	}
	int mid=(l+r)/2;
	now=id[mid];
	build(l,mid-1,mid);
	build(mid+1,r,mid);
	tree[now].f=last;
	pushup(mid);
	if(mid<f)
		tree[last].l=now;
	else
		tree[last].r=now;
}
void zig(int &x)
{
	int fa=tree[x].f;
	int grfa=tree[fa].f;
	if(tree[grfa].l==fa)
		tree[grfa].l=x;
	else
		tree[grfa].r=x;
	tree[x].f=grfa;
	tree[fa].l=tree[x].r;
	tree[tree[x].r].f=fa;
	tree[x].r=fa;
	tree[fa].f=x;
	pushup(fa);
	pushup(x);
	if(fa==root)
		root=x;
}
void zag(int &x)
{
	int fa=tree[x].f;
	int grfa=tree[fa].f;
	if(tree[grfa].r==fa)
		tree[grfa].r=x;
	else
		tree[grfa].l=x;
	tree[x].f=grfa;
	tree[fa].r=tree[x].l;
	tree[tree[x].l].f=fa;
	tree[x].l=fa;
	tree[fa].f=x;
	pushup(fa);
	pushup(x);
	if(fa==root)
		root=x;
}
void splay(int &x,int d)
{
	while(tree[x].f!=d)
	{
		if(x==tree[tree[x].f].l)
			zig(x);
		else
			zag(x);
	}
}
int find(int x,int k)
{
	//cout<<x<<" "<<k<<endl;
	if(tree[x].rev)
		pushdown(x);
	if(k<=tree[tree[x].l].s)
	{
		//cout<<tree[x].l<<" "<<k<<" "<<tree[tree[x].l].s<<endl;
		return find(tree[x].l,k);
	}
	if(k==tree[tree[x].l].s+1)
		return x;
	return find(tree[x].r,k-tree[tree[x].l].s-1);
}
void rev(int l,int r)
{
	int x=find(root,l);
	int y=find(root,r+2);
	//cout<<x<<" "<<y<<endl;
	splay(x,0);
	//cout<<tree[0].s<<"LLLLL"<<endl;
	splay(y,x);
	int now=tree[y].l;
	tree[now].rev^=1;
	//cout<<tree[0].s<<"LLLLL"<<endl;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n+2;i++)
	{
		id[i]=i;
	}
	root=(n+3)>>1;
	build(1,n+2,0);
	for(int i=1;i<=m;i++)
	{
		int a,b;
		scanf("%d%d",&a,&b);
		rev(a,b);
	}
	for(int i=2;i<=n+1;i++)
	{
		printf("%d ",find(root,i)-1);
	} 
 } 

bzoj1588
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int N=50005;
struct node
{
	int l,r,fa,v,s,num;
}tree[N];
int n,root,cnt;
void pushup(int rt)
{
	tree[rt].s=tree[tree[rt].l].s+tree[tree[rt].r].s+1;
}
void zig(int &rt)
{
	int fa=tree[rt].fa;
	int grfa=tree[fa].fa;
	if(fa==tree[grfa].l)
		tree[grfa].l=rt;
	else
		tree[grfa].r=rt;
	tree[rt].fa=grfa;
	tree[fa].l=tree[rt].r;
	tree[tree[rt].r].fa=fa;
	tree[fa].fa=rt;
	tree[rt].r=fa;
	pushup(rt);
	pushup(fa);
	if(fa==root)
		root=rt;
}
void zag(int &rt)
{
	int fa=tree[rt].fa;
	int grfa=tree[fa].fa;
	if(tree[grfa].l==fa)
		tree[grfa].l=rt;
	else
		tree[grfa].r=rt;
	tree[rt].fa=grfa;
	tree[fa].r=tree[rt].l;
	tree[tree[rt].l].fa=fa;
	tree[fa].fa=rt;
	tree[rt].l=fa;
	pushup(rt);
	pushup(fa);
	if(root==fa)
		root=rt;
}
void splay(int &rt,int d)
{
	while(tree[rt].fa!=d)
	{
		if(tree[tree[rt].fa].l==rt)
			zig(rt);
		else
			zag(rt);
	}
}
void insert(int rt)
{
	if(!root)
	{
		root=++cnt;
		tree[cnt].s=1;
		tree[cnt].num=rt;
		return ;
	}
	int z=root,p;
	while(z)
	{
		p=z;
		tree[z].s++;
		if(rt>tree[z].num)
			z=tree[z].r;
		else
			z=tree[z].l;
	}
	tree[++cnt].s=1;
	tree[cnt].num=rt;
	tree[cnt].fa=p;
	if(rt>tree[p].num)
		tree[p].r=cnt;
	else
		tree[p].l=cnt;
	splay(cnt,0);
}
int ask1(int rt)
{
	if(!tree[rt].r)
		return tree[rt].num;
	else
		return ask1(tree[rt].r);
}
int ask2(int rt)
{
	if(!tree[rt].l)
		return tree[rt].num;
	else
		return ask2(tree[rt].l);
}
int ans=0;
int main()
{
	scanf("%d",&n);
	int a;
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a);
		insert(a);
		//cout<<tree[root].l<<" l:"<<tree[tree[root].l].num<<endl;
		//cout<<tree[root].r<<" r:"<<tree[tree[root].r].num<<endl;
		if((!tree[root].l)&&(!tree[root].r))
			ans+=a;
		else
		if(!tree[root].r)
			ans+=(a-ask1(tree[root].l));
		else
		if(!tree[root].l)
			ans+=(ask2(tree[root].r)-a);
		else
		ans+=min((a-ask1(tree[root].l)),(ask2(tree[root].r)-a));
		//cout<<ans<<endl;
	}
	cout<<ans;
}

bzoj1500(rewrite)
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h> 
#include<stdio.h>
#include<queue>
using namespace std;
const int N=1000050;
const int INF=1000000000;
int c[N][2],fa[N],cnt,id[N],a[N];
int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
queue<int> q;
int root;
struct node
{
	int mx,lx,rx,v,size,sum;
	bool tag,rev;
}tree[N];
void pushup(int rt)
{
	int l=c[rt][0],r=c[rt][1];
	tree[rt].mx=max(tree[l].mx,max(tree[r].mx,tree[l].rx+tree[r].lx+tree[rt].v));
	tree[rt].lx=max(tree[l].lx,tree[l].sum+tree[rt].v+tree[r].lx);
	tree[rt].rx=max(tree[r].rx,tree[r].sum+tree[rt].v+tree[l].rx);
	tree[rt].size=tree[l].size+tree[r].size+1;
	tree[rt].sum=tree[rt].v+tree[l].sum+tree[r].sum; 
}
void revv(int rt)
{
	swap(c[rt][0],c[rt][1]);
	swap(tree[rt].lx,tree[rt].rx);
}
void pushdown(int rt)
{
	int l=c[rt][0],r=c[rt][1];
	if(tree[rt].tag)
	{
		tree[rt].tag=tree[rt].rev=0;
		if(l)	tree[l].tag=1,tree[l].v=tree[rt].v,tree[l].sum=tree[l].size*tree[l].v,tree[l].lx=tree[l].rx=max(0,tree[l].sum),tree[l].mx=max(tree[l].sum,tree[l].v);
		if(r)	tree[r].tag=1,tree[r].v=tree[rt].v,tree[r].sum=tree[r].size*tree[r].v,tree[r].lx=tree[r].rx=max(0,tree[r].sum),tree[r].mx=max(tree[r].sum,tree[r].v);
	}
	if(tree[rt].rev)
	{
		tree[rt].rev=0;
		if(l)	tree[l].rev^=1,revv(l);
		if(r)	tree[r].rev^=1,revv(r);
	}
}
void rotate(int x,int &k)
{
	int y=fa[x],z=fa[y],l,r;
	l=(c[y][1]==x),r=l^1;
	if(y==k)
		k=x;
	else
		c[z][c[z][1]==y]=x;
	fa[c[x][r]]=y;
	fa[y]=x;
	fa[x]=z;
	c[y][l]=c[x][r];
	c[x][r]=y;
	pushup(y);
	pushup(x);
}
void splay(int x,int &k)
{
	while(x!=k)
	{
		int y=fa[x],z=fa[y];
		if(y!=k)
		{
			if((c[y][0]==x)^(c[z][0]==y))	rotate(x,k);
			else rotate(y,k);
		}
		rotate(x,k);
	}
}
int find(int rk,int rt)
{
	pushdown(rt);
	int l=c[rt][0],r=c[rt][1];
	if(tree[l].size>=rk)
		return find(rk,l);
	if(rk==tree[l].size+1)
		return rt;
	return find(rk-tree[l].size-1,r);
}
void rec(int x)
{
	if(!x)
		return ;
	int l=c[x][0],r=c[x][1];
	rec(l),rec(r),q.push(x);
	c[x][0]=c[x][1]=fa[x]=0;
	tree[x].lx=tree[x].rx=tree[x].mx=tree[x].sum=fa[x]=tree[x].tag=tree[x].v=tree[x].size=tree[x].rev=0;
}
int split(int k,int tot)
{
	int l1=find(k,root);
	int l2=find(k+1+tot,root);
	splay(l1,root),splay(l2,c[l1][1]);
	return c[l2][0];
}
void query(int k,int tot)
{
	int f=split(k,tot);
	printf("%d\n",tree[f].sum); 
} 
void modify(int k,int tot,int val)
{
	int x=split(k,tot);
	int y=fa[x];
	tree[x].tag=1;
	tree[x].v=val;
	tree[x].sum=val*tree[x].size;
	if(val>=0)	tree[x].lx=tree[x].rx=tree[x].mx=tree[x].sum;
	else	tree[x].lx=tree[x].rx=0,tree[x].mx=tree[x].v;
	pushup(y);
	pushup(fa[y]);
}
void rever(int k,int tot)
{
	int x=split(k,tot),y=fa[x];
	if(!tree[x].tag)
	{
		revv(x);
		tree[x].rev^=1;
		pushup(y),pushup(fa[y]);
	}	
}
void erase(int k,int tot)
{
	int x=split(k,tot),y=fa[x];
	rec(x),c[y][0]=0;
	pushup(y),pushup(fa[y]);
}
void build(int l,int r,int f)
{
	if(l>r)
		return ;
	int mid=(l+r)/2,now=id[mid],last=id[f];
	if(l==r)
	{
		tree[now].sum=a[l];
		tree[now].size=1;
		tree[now].lx=tree[now].rx=max(a[l],0),tree[now].mx=a[l];
		tree[now].tag=tree[now].rev=0;
	}
	else
		build(l,mid-1,mid),build(mid+1,r,mid);
	tree[now].v=a[mid];fa[now]=last;
	pushup(now);
	c[last][mid>=f]=now;
}
void ins(int k,int tot)
{
	for(int i=1;i<=tot;i++)
		a[i]=read();
	for(int i=1;i<=tot;i++)
		if(!q.empty())	id[i]=q.front(),q.pop();
		else	id[i]=++cnt;
	build(1,tot,0);
	int z=id[(1+tot)>>1];
	int x=find(k+1,root),y=find(k+2,root);
	splay(x,root);
	splay(y,c[x][1]);
	fa[z]=y,c[y][0]=z;
	pushup(y);
	pushup(x);
}
char s[20];
int a1,b1,c1,n,m;
int main()
{
	scanf("%d%d",&n,&m);
	a[1]=a[n+2]=tree[0].mx=-INF;
	for(int i=1;i<=n;i++)
		a[i+1]=read(),id[i]=i;
	id[n+1]=n+1,id[n+2]=n+2; 
	root=(n+3)>>1,cnt=n+2;
	build(1,n+2,0);
	for(int i=1;i<=m;i++)
	{
		scanf("%s",s);
		if(s[0]=='G')
			a1=read(),b1=read(),query(a1,b1);
		else if(s[0]=='I')
			a1=read(),b1=read(),ins(a1,b1);
		else if(s[0]=='D')
			a1=read(),b1=read(),erase(a1,b1);
		else if(s[0]=='M'&&s[2]=='X')
			printf("%d\n",tree[root].mx);
		else if(s[0]=='M')
			a1=read(),b1=read(),c1=read(),modify(a1,b1,c1);
		else if(s[0]=='R')
			a1=read(),b1=read(),rever(a1,b1);
	}
}

应用:
bzoj1208
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;
const int N=80050;
long long ans; 
int c[N][2],a[N],root,v[N],lx[N],rx[N],id[N],mx[N],sum[N],fa[N],cnt;
void rotate(int x,int &k)
{
	int y=fa[x],z=fa[y];
	int l=(c[y][1]==x);
	int r=l^1;
	if(y==k)
		k=x;
	else
		c[z][c[z][1]==y]=x;
	fa[c[x][r]]=y;
	fa[y]=x;
	fa[x]=z;
	c[y][l]=c[x][r];
	c[x][r]=y;
}
void splay(int x,int &k)
{
	int y,z;
	while(x!=k)
	{
		y=fa[x],z=fa[y];
		if(y!=k)
		{
			if((c[y][0]==x)^(c[z][0]==y))
				rotate(x,k);
			else
				rotate(y,k);
		}
		rotate(x,k);
	}
}
void ins(int &k,int x,int last)
{
	if(k==0)
	{
		k=++cnt;
		v[k]=x;
		fa[k]=last;
		splay(k,root);
		return ;
	}
	if(x<v[k])
		ins(c[k][0],x,k);
	else
		ins(c[k][1],x,k);
}
void del(int x)
{
	splay(x,root);
//	cout<<c[x][0]<<" "<<c[x][1]<<endl;
	if(!(c[x][0]*c[x][1]))
	root=c[x][0]+c[x][1];
	else
	{
		int k=c[x][1];
		while(c[k][0])
			k=c[k][0];
		c[k][0]=c[x][0];
		fa[c[x][0]]=k;
		root=c[x][1];
//		cout<<"OK"<<endl;
	}
//	cout<<root<<"PPPPPP"<<endl;
	fa[root]=0;
}	
int t1,t2;
void find1(int x,int aim)
{
	if(x==0)
		return ;
	if(v[x]<=aim)
		t1=x,find1(c[x][1],aim);
	else
		find1(c[x][0],aim);
}
void find2(int x,int aim)
{
	if(x==0)
		return ;
	if(v[x]>=aim)
		t2=x,find2(c[x][0],aim);
	else
		find2(c[x][1],aim);
}
int n,t,b,kind;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&t,&b);
//		cout<<"kind:"<<kind<<" root"<<root<<endl;
		if(!root)
		{
			ins(root,b,0);
			kind=t;
		}
		else
		if(t==kind)
			ins(root,b,0);
		else
		{
			t1=t2=-1;
			find1(root,b);
			find2(root,b);
//			cout<<"t1:"<<t1<<" t2:"<<t2<<endl;
			if(t1==-1)
				ans=(ans+v[t2]-b)%1000000,del(t2);
			else if(t2==-1)
				ans=(ans+b-v[t1])%1000000,del(t1);
			else
			if(t1>=0&&t2>=0&&v[t2]-b<b-v[t1])
			{
				ans=(ans+v[t2]-b)%1000000;
				del(t2);
			}
			else
				ans=(ans+b-v[t1])%1000000,del(t1);
		}
//		cout<<"LLLLL";
	}
	printf("%d\n",ans);
}

bzoj2329
神题
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int N=1000050;
int n,m;
char s[1000050];
int a[N],id[N],fa[N],root;
int c[N][2];
struct node
{
	int lx,lm,rx,rm,sum,v,size;
	int rev,tag1,tag2;
}tree[N];
void tong1(int rt,int vl)
{
	tree[rt].v=vl,tree[rt].tag2=tree[rt].rev=0,tree[rt].tag1=vl;
	tree[rt].sum=tree[rt].size*vl;
	tree[rt].lx=tree[rt].rx=max(tree[rt].sum,0);
	tree[rt].lm=tree[rt].rm=min(tree[rt].sum,0);
}
void tong2(int rt)
{
	tree[rt].lm=-tree[rt].lm,tree[rt].lx=-tree[rt].lx;
	tree[rt].rm=-tree[rt].rm,tree[rt].rx=-tree[rt].rx;
	swap(tree[rt].lx,tree[rt].lm),swap(tree[rt].rm,tree[rt].rx);	
	tree[rt].sum=-tree[rt].sum,tree[rt].v=-tree[rt].v;
	if(tree[rt].tag1)tree[rt].tag1=-tree[rt].tag1;
	else tree[rt].tag2^=1;
}
void revv(int rt)
{
	swap(tree[rt].lx,tree[rt].rx);
	swap(tree[rt].rm,tree[rt].lm);
	swap(c[rt][0],c[rt][1]);
	tree[rt].rev^=1;
}
void pushdown(int rt)
{
	int l=c[rt][0],r=c[rt][1];
	if(tree[rt].tag2)
	{
		if(l)	tong2(l);
		if(r)	tong2(r);	
		tree[rt].tag2^=1;		
	}
	if(tree[rt].rev)
	{
		if(l) revv(l);
		if(r) revv(r);
		tree[rt].rev^=1;
	}	
	if(tree[rt].tag1)
	{
		if(l)	tong1(l,tree[rt].tag1);
		if(r)	tong1(r,tree[rt].tag1);		
		tree[rt].tag1=0;	
	}
}
void pushup(int rt)
{
	int l=c[rt][0],r=c[rt][1];
	tree[rt].lm=min(tree[l].lm,tree[l].sum+tree[r].lm+tree[rt].v);
	tree[rt].rm=min(tree[r].rm,tree[r].sum+tree[l].rm+tree[rt].v);
	tree[rt].lx=max(tree[l].lx,tree[l].sum+tree[r].lx+tree[rt].v);
	tree[rt].rx=max(tree[r].rx,tree[r].sum+tree[l].rx+tree[rt].v);
	tree[rt].size=tree[l].size+tree[r].size+1;
	tree[rt].sum=tree[l].sum+tree[r].sum+tree[rt].v;
}
void build(int l,int r,int f)
{
	if(l>r)
		return;
	int mid=(l+r)/2,rt=id[mid],last=id[f];
	if(l==r)
	{
		tree[rt].size=1;
		tree[rt].sum=a[l];
		tree[rt].tag1=tree[rt].tag2=tree[rt].rev=0;
		tree[rt].lx=tree[rt].rx=max(0,tree[rt].v);
		tree[rt].lm=tree[rt].rm=min(0,tree[rt].v);
	}
	else	build(l,mid-1,mid),build(mid+1,r,mid);
	tree[rt].v=a[mid];
	fa[rt]=last;
	pushup(rt);
	c[last][mid>=f]=rt;
}
void rotate(int x,int &k)
{
	int y=fa[x],z=fa[y];
	int l=c[y][1]==x,r=l^1;
	if(y==k)
		k=x;
	else
		c[z][c[z][1]==y]=x;
	fa[c[x][r]]=y;
	fa[x]=z;
	fa[y]=x;
	c[y][l]=c[x][r];
	c[x][r]=y;
	pushup(y);
	pushup(x);
}
void splay(int x,int &k)
{
	while(x!=k)
	{
		int y=fa[x],z=fa[y];
		if(y!=k)
		{
			if(c[z][0]==y^c[y][0]==x)	rotate(x,k);
			else	rotate(y,k);
		}
		rotate(x,k);
	}
}
int find(int rt,int rk)
{
	pushdown(rt);
	int l=c[rt][0],r=c[rt][1];
	if(tree[l].size>=rk)
		return find(l,rk);
	if(tree[l].size+1==rk)
		return rt;
	return find(r,rk-tree[l].size-1);
}
int split(int l,int r)
{
	int l1=find(root,l),r1=find(root,r+2);
//	cout<<l1<<" "<<r1<<endl;
	splay(l1,root),splay(r1,c[l1][1]);
	return c[r1][0];
}
char fanzhuan(int x)
{
	return 	x==1 ?'(':')';
}
void dfs(int x)
{
	pushdown(x);
	if(c[x][0])	dfs(c[x][0]);
	cout<<fanzhuan(tree[x].v);
	if(c[x][1])	dfs(c[x][1]);
}
void repl(int l,int r,int vl)
{
	int x=split(l,r),y=fa[x];
//	dfs(x);
//	cout<<endl;
	tong1(x,vl);
	pushup(y);
	pushup(fa[y]);
}
void rever(int l,int r)
{
	int x=split(l,r),y=fa[x];
	revv(x);
	pushup(y),pushup(fa[y]);	
//	dfs(x);
//	cout<<endl;
}
void fan(int l,int r)
{
	int x=split(l,r),y=fa[x];
	tong2(x);
	pushup(y),pushup(fa[y]);
}
void query(int l,int r)
{
	int x=split(l,r);
	printf("%d\n",(-tree[x].lm+1)/2+(tree[x].rx+1)/2);
}
int a1,b1;
char c1;
int zhuan(char x)
{
	return 	x=='(' ?1:-1;
}
int main()
{
	scanf("%d%d",&n,&m);
	scanf("%s",s);
	for(int i=1;i<=n;i++)
		a[i+1]= s[i-1]=='(' ?1:-1;
	for(int i=1;i<=n+2;i++)
		id[i]=i;
	build(1,n+2,0);
	root=(n+3)>>1;
	for(int i=1;i<=m;i++)		
	{
		scanf("%s",s);
		if(s[0]=='R')
			scanf("%d%d%c%c",&a1,&b1,&c1,&c1),repl(a1,b1,zhuan(c1));
		else if(s[0]=='I')
			scanf("%d%d",&a1,&b1),fan(a1,b1);
		else if(s[0]=='S')
			scanf("%d%d",&a1,&b1),rever(a1,b1);
		else
			scanf("%d%d",&a1,&b1),query(a1,b1);
	}	
} 

特殊:
操作:将一个区间[l,r]内的数字旋转k次(每次旋转区间内每个元素向右移一位,最右一个移动到最左面去)
将区间[l,r]分为[l,r-k],[r-k+1,r],那么这个操作的实质就是将[l,r-k]插到[r-k+1,r]的右边去,实质则是一次del操作+一次ins操作
                                                                                                                         (from poj3580)


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值