数据结构 day 4 splay 平衡树初步

抓梦脚的一天。。。

给你一个长为n 的序列:a1; a2; : : : ; an
你需完成q 个操作,操作分两种:
• modify l r d 表示将l 到r 这个区间的数加上d
• query p 表示询问p 这个位置的值
Input
第一行一个整数n。
第二行n 个整数表示a1; a2; : : : ; an。
第三行一个整数q。
接下来q 行,每行一个操作。
Output
对于每个询问操作,输出结果。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=400005;
int n,q;
int a[maxn],tag[maxn],f[maxn];
bool flag[maxn];
void update(int o)
{
	f[o]=f[o*2]+f[o*2+1];
}
void build(int o,int lf,int rg)
{
	if (lf==rg)
	{
		f[o]=a[lf];
		return ;
	}
	int mid=(lf+rg)>>1;
	build(o*2,lf,mid);
	build(o*2+1,mid+1,rg);
	update(o);
}
void push_down(int o,int lf,int rg)
{
	if (flag[o]==1)
	{
		int mid=(lf+rg)>>1;
		f[o*2]+=tag[o]*(mid-lf+1);
		f[o*2+1]+=tag[o]*(rg-mid);
		tag[o*2]+=tag[o];
		tag[o*2+1]+=tag[o];
		flag[o*2]=flag[o*2+1]=1;
		tag[o]=0;
		flag[o]=0;
	}
}
void modify(int o,int lf,int rg,int L,int R,int de)
{
	if (lf>=L&&rg<=R)
	{
		f[o]+=de*(rg-lf+1);
		tag[o]+=de;
		flag[o]=1;
		return ;
	}
	push_down(o,lf,rg);
	int mid=(lf+rg)>>1;
	if (L<=mid)
	   modify(o*2,lf,mid,L,R,de);
	if (R>mid)
	   modify(o*2+1,mid+1,rg,L,R,de);
	update(o);
}
int query(int o,int lf,int rg,const int L,const int R)
{
	int ans=0;
	if (lf>=L&&rg<=R)
	return f[o];
	push_down(o,lf,rg);
	int mid=(lf+rg)>>1;
	if (L<=mid)
	  ans+=query(o*2,lf,mid,L,R);
	if (R>mid)
	  ans+=query(o*2+1,mid+1,rg,L,R);
	return ans;
}
int main()
{
	freopen("bit.in","r",stdin);
	freopen("bit.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	  scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&q);
	for (int i=1;i<=q;i++)
	{
		string s1;
		cin>>s1;
		if (s1[0]=='m')
		{
			int l;int r;int de;
			scanf("%d%d%d",&l,&r,&de);
			modify(1,1,n,l,r,de);
		}
		if (s1[0]=='q')
		{
			int x;
			scanf("%d",&x);
			printf("%d\n",query(1,1,n,x,x));
		}
	}
	return 0;
}
/*
3
1 2 3
3
query 2
modify 1 3 -2
query 2
*/

给你一个序列,需要你执行两种操作:
• modify l r A B 将区间[l; r] 中每个数ai 修改为Aai + B。
• query l r 询问区间[l; r] 中所有数的和,输出和对109 + 7 取模的结果。
Input
第1 行,一个整数N,表示序列长度。
第2 行,有N 个整数:a1; a2; : : : ; an 表示序列。
接下来1 行,一个整数Q,表示询问数。
接下来Q 行,每行一个操作。
Output

对于每个询问,输出结果。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
const int maxn=4000005;
long long tagadd[maxn],tagmul[maxn],a[maxn],f[maxn];
bool flag[maxn];
int n,q;
void update(int o)
{
	f[o]=(f[o*2]%mod+f[o*2+1]%mod)%mod;
}
void build(int o,int lf,int rg)
{
	if (lf==rg)
	{
		f[o]=a[lf]%mod;
		return ;
	}
	int mid=(lf+rg)>>1;
	build(o*2,lf,mid);
	build(o*2+1,mid+1,rg);
	update(o);
}
void push_down(int o,int lf,int rg)
{
	if (flag[o]==1)
	{
		int mid=(lf+rg)>>1;
		f[o*2]=(f[o*2]%mod*tagmul[o]%mod+tagadd[o]*(mid-lf+1)%mod)%mod;
		f[o*2+1]=(f[o*2+1]%mod*tagmul[o]%mod+tagadd[o]*(rg-mid)%mod)%mod;
		tagadd[o*2]=(tagadd[o*2]%mod*tagmul[o]%mod+tagadd[o])%mod;
		tagadd[o*2+1]=(tagadd[o*2+1]%mod*tagmul[o]%mod+tagadd[o])%mod;
		tagmul[o*2]=tagmul[o*2]%mod*tagmul[o]%mod;
		tagmul[o*2+1]=tagmul[o*2+1]%mod*tagmul[o]%mod;
		flag[o*2]=flag[o*2+1]=1;
		tagadd[o]=0;
		tagmul[o]=1;
		flag[o]=0;
	}
}
void modify(int o,int lf,int rg,const int L,const int R,long long ch,long long he)
{
	if (lf>=L&&rg<=R)
	{
		f[o]=((f[o]*ch%mod+he*(rg-lf+1))%mod)%mod;
		tagadd[o]=(tagadd[o]*ch%mod+he)%mod;
		tagmul[o]=(tagmul[o]%mod*ch)%mod;
		flag[o]=1;
		return ;
	}
	push_down(o,lf,rg);
	int mid=(lf+rg)>>1;
	if (L<=mid)
	   modify(o*2,lf,mid,L,R,ch,he);
	if (R>mid)
	   modify(o*2+1,mid+1,rg,L,R,ch,he);
	update(o);
}
long long query(int o,int lf,int rg,const int L,const int R)
{
	long long ans=0;
	if (lf>=L&&rg<=R)
	return f[o]%mod;
	push_down(o,lf,rg);
	int mid=(lf+rg)>>1;
	if (L<=mid)
	  ans+=query(o*2,lf,mid,L,R)%mod;
	if (R>mid)
	  ans+=query(o*2+1,mid+1,rg,L,R)%mod;
	return ans%mod;
}
int readint()
{
	char xy=' ';int cc=0;
	int pd=1;
	while(xy==' '||xy=='\n')xy=getchar();
	if(xy=='-'){pd=-1;xy=getchar();}
	while(xy!=' '&&xy!='\n')
	{
		cc=cc*10+(xy-'0');
		xy=getchar();
	}
	return cc*pd;
}
long long readlong()
{
	char xy=' ';long long cc=0;
	long long pd=1;
	while(xy==' '||xy=='\n')xy=getchar();
	if(xy=='-'){pd=-1;xy=getchar();}
	while(xy!=' '&&xy!='\n')
	{
		cc=cc*10+(xy-'0');
		xy=getchar();
	}
	return cc*pd;
}
int main()
{
	freopen("linear.in","r",stdin);
	freopen("linear.out","w",stdout);
	n=readint();
	for (int i=1;i<=n;i++)
	{
		a[i]=readlong();
	}
	for (int i=1;i<=maxn-1;i++)
	   tagmul[i]=1;
	build(1,1,n);
	q=readint();
	for (int i=1;i<=q;i++)
	{
		string s1;
		cin>>s1;
		if (s1[0]=='q')
		{
			int l,r;
			l=readint();
			r=readint();
			printf("%d\n",query(1,1,n,l,r));
		}
		if (s1[0]=='m')
		{
			int l,r,A,B;
			l=readint();
			r=readint();
			A=readint();
			B=readint();
			modify(1,1,n,l,r,A,B);
		}
	}
	return 0;
}
/*
3
1 2 3
3
query 1 3
modify 2 3 2 3
query 1 3
*/

给你一个长度为N 的序列,有M 个操作,操作有两种类型,如下所示:
• D pos 表示删除位置为pos 的数。
• Q pos 表示询问位置为pos 的数是什么。
Input
第1 行,两个整数N;M;
第2 行,N 个整数:a1; a2; : : : ; an 表示初始序列;
接下来M 行,每行是上面两种操作之一。
Output

对于每个询问,输出其对应结果。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=400005;

int val[N],fa[N],n,idc,a[N],son[N][2],size[N],root;
char s1[15];
void update(int o)
{
	size[o]=size[son[o][0]]+size[son[o][1]]+1;
}
int build(int f,int o,int l,int r)
{
	if(l>r) return 0;
	int mid=(l+r)/2;
	fa[o]=f;
	son[o][0]=build(o,o*2,l,mid-1);
	son[o][1]=build(o,o*2+1,mid+1,r);
	val[o]=a[mid];
	update(o);
	return o;
}
void init(int o)
{
	root=build(0,1,1,n+2);
}
void rotate(int o,int d)
{
	int s=son[o][!d],ss=son[s][d];
	int p=fa[o];
	son[o][!d]=son[s][d];
	son[s][d]=o;
	if(ss) fa[ss]=o;
	son[p][o==son[p][1]]=s;	
	if(!p) root=s;
	fa[o]=s;
	fa[s]=p;
	update(o);
	update(s);
}
void splay(int nd,int top=0)
{
	while(fa[nd]!=top)
	{	
	int baba=fa[nd];
	int dl=nd==son[baba][0];
    if(fa[baba]==top)
      rotate(baba,dl);
	else
	{    
	    int yeye=fa[baba];
		int pl=baba==son[yeye][0];
	   if(pl==dl)
	   {     
	   	   rotate(yeye,pl);
		   rotate(baba,dl);		   
	   }	
	   else
	   {       
	        rotate(baba,dl);  
			rotate(yeye,pl);        
	   }
	}	
	}
}
int find(int pos)
{
	int s=root;
	while(1)
	{
		int lf=size[son[s][0]];
		if(lf>=pos){
			s=son[s][0];
		} 
		else if(lf<=pos-2)
		  {
		  	pos-=lf+1;
		  	s=son[s][1];
		  }
		else return s;
	}
} 
void del(int pos)
{
	int lf=find(pos-1);
	int rg=find(pos+1);
	splay(lf);
	splay(rg,lf);
	son[rg][0]=0;
	update(rg);
	update(lf);
}
int readint()
{
	char xy=' ';int cc=0;
	int pd=1;
	while(xy==' '||xy=='\n')xy=getchar();
	if(xy=='-'){pd=-1;xy=getchar();}
	while(xy!=' '&&xy!='\n')
	{
		cc=cc*10+(xy-'0');
		xy=getchar();
	}
	return cc*pd;
}
long long readlong()
{
	char xy=' ';long long cc=0;
	long long pd=1;
	while(xy==' '||xy=='\n')xy=getchar();
	if(xy=='-'){pd=-1;xy=getchar();}
	while(xy!=' '&&xy!='\n')
	{
		cc=cc*10+(xy-'0');
		xy=getchar();
	}
	return cc*pd;
}
int main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	int m;
	cin>>n>>m;
	a[1]=0,a[n+2]=0;
	for(int i=2;i<=n+1;i++)
	    a[i]=readint();
	init(1);
//for(int i = 1; i <= n + 2 ; i++ )
		//printf("nd  = %d s[0] = %d s[1] = %d val = %d\n",i, son[i][0], son[i][1],val[i]);
    for(int i=1;i<=m;i++)
    {
    	int x1;
    	scanf("%s",&s1);
    	if(s1[0]=='Q')
    	{   
		    int ans; 
    		x1=readint();
    		ans=val[find(x1+1)];
    		printf("%d\n",ans);
    	}
    	if(s1[0]=='D')
    	{
    		x1=readint();
    		del(x1+1);
    	}
    }    
	return 0;
}

读入优化真的跑的飞快

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值