您的位置:首页 > 其它

hiho 1333 : 平衡树 splay 区间删除,更新,查询,单点插入

2017-06-03 23:22 483 查看
题目链接点这里

展现spaly的强大功能的#include<iostream>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define FIN freopen("input.txt","r",stdin);
typedef long long LL;
#define MX 1111111
int n;
int son[MX][2],fa[MX],key[MX],siz[MX],root;
LL val[MX],lazy[MX],sum[MX];
int cnt;
void Pushup(int rt)
{
int ls=son[rt][0],rs=son[rt][1];
siz[rt]=1,sum[rt]=val[rt];
if(ls) siz[rt]+=siz[ls],sum[rt]+=sum[ls];
if(rs) siz[rt]+=siz[rs],sum[rt]+=sum[rs];
}
void Pushdown(int rt)
{
if(lazy[rt])
{
int ls=son[rt][0],rs=son[rt][1];
if(ls)lazy[ls]+=lazy[rt],sum[ls]+=siz[ls]*lazy[rt],val[ls]+=lazy[rt];
if(rs)lazy[rs]+=lazy[rt],sum[rs]+=siz[rs]*lazy[rt],val[rs]+=lazy[rt];
lazy[rt]=0;
}
}
int New_nod(int f,int k,int v)
{
cnt++;
son[cnt][0]=son[cnt][1]=0;
fa[cnt]=f;
siz[cnt]=1;
key[cnt]=k;
val[cnt]=v;
sum[cnt]=v;
return cnt;
}
void Splay_init()
{
cnt=0;
root=New_nod(0,-INF,0);//先加了2个边界点
son[root][1]=New_nod(root,INF,0);
Pushup(root);
}
void Rotate(int x,int c)//c==0代表右旋
{
int nxtf=fa[fa[x]],f=fa[x];
Pushdown(f),Pushdown(x);
if(nxtf!=0)son[nxtf][son[nxtf][0]!=f]=x;
fa[x]=nxtf;
son[f][c]=son[x][!c];
fa[son[x][!c]]=f;
son[x][!c]=f;
fa[f]=x;
Pushup(f);
}
void Splay(int x,int y)//把x旋转为y的子节点,首先要确保y是x的祖先
{
Pushdown(x);
while(fa[x]!=y)
{
int f=fa[x];
int c1=(son[fa[f]][0]==f),c2=(son[f][0]==x);
if(fa[f]==y)Rotate(x,!c2);
else
{
if(c1^c2)Rotate(x,!c2),Rotate(x,c2);
else Rotate(f,!c1),Rotate(x,!c1);;
}
}
Pushup(x);
if(!y)root=x;
}
int Insert(int x,int val)
{
int now=root,f;
while(now!=0)
{
Pushdown(now);
siz[now]++;
sum[now]+=val;
f=now;
now=son[now][x>=key[now]];
}
int id=New_nod(f,x,val);
son[f][x>=key[f]]=id;
Splay(id,0);
return id;
}
int Find(int x)
{
int now=root;
while(now)
{
Pushdown(now);
if(key[now]==x)return now;
now=son[now][x>=key[now]];
}
return now;
}
int Findpre(int x)//查询严格小于x的节点
{
int now=root;
int ans;
while(now)
{
Pushdown(now);
if(key[now]<x)ans=now,now=son[now][1];
else now=son[now][0];
}
return ans;
}
int Findnxt(int x)//查询严格大于x的节点
{
int now=root;
int ans;
while(now)
{
Pushdown(now);
if(key[now]>x)ans=now,now=son[now][0];
else now=son[now][1];
}
return ans;
}
void Delete(int l,int r)
{
int x=Findpre(l);
int y=Findnxt(r);
Splay(x,0);
Splay(y,x);
son[y][0]=0;//内存不够时写内存池
Pushup(y);
Pushup(x);
}
LL Query(int l,int r)
{
int x=Findpre(l);
int y=Findnxt(r);
Splay(x,0);
Splay(y,x);
return sum[son[y][0]] ;
}

void Update(int l,int r,int v)
{

int x=Findpre(l);
int y=Findnxt(r);
Splay(x,0);
Splay(y,x);
int id=son[y][0];
sum[id]+=(LL)siz[id]*v;
val[id]+=v;
lazy[id]+=v;
Pushup(y);
Pushup(x);
}
int main()
{
FIN;
Splay_init();
cin>>n;
for(int i=1; i<=n; i++)
{
char s[10];
int x,y,d;
scanf("%s",s);
if(s[0]=='I')
{
scanf("%d%d",&x,&y);
Insert(x,y);
}
else if(s[0]=='Q')
{

scanf("%d%d",&x,&y);
printf("%lld\n",Query(x,y));
}
else if(s[0]=='D')
{
scanf("%d%d",&x,&y);
Delete(x,y);
}
else
{
scanf("%d%d%d",&x,&y,&d);
Update(x,y,d);
}
}
return 0;
}


小小一题,虽然也写了很久,,好多地方需要注意的。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: