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;
}
小小一题,虽然也写了很久,,好多地方需要注意的。。
展现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;
}
小小一题,虽然也写了很久,,好多地方需要注意的。。
相关文章推荐
- POJ 3580 SuperMemo (Splay 区间更新、翻转、循环右移,插入,删除,查询)
- 【数据结构SPLAY】splay区间翻转,区间和查询,区间插入,区间删除,区间修改
- HihoCoder1333 :平衡树(splay+lazy)(区间加值,区间删除)
- fastdb中记录的插入,更新,和删除,查询
- ThinkPHP 数据库操作,插入,更新,删除,查询
- HDU ACM 4031 Attack (树状数组--单点查询+区间更新)
- sql存储过程 1查询;2插入;3更新;4删除
- DedeCms二次开发之简单的查询、插入、更新、删除操作实例
- poj 2828(线段树:单点插入,区间查询)
- Android Sqlite数据库执行插入查询更新删除的操作对比
- 树状数组:HDU1556 Color the ball 【区间更新,单点查询]
- Splay解决区间问题[单点更新,区间最值询问]
- 线段树 HDU 4217 Data Structure? 单点更新 区间查询
- 在C#下使用sql语句(查询,插入,更新,删除……)
- Linq的技术太强大了分享一下(linq to sql 的插入、更新、查询、删除)
- 线段树(堆式)[单点更新, 区间查询]
- HDOJ-2795 Billboard [线段树][单点更新+单点查询+维护区间最值]
- zoj (单点更新区间查询:线段树)
- POJ 3264 Balanced Lineup(线段树 单点更新 区间查询)
- vc++连接mysql数据库,并对数据库中的表进行查询、插入、删除、更新等