您的位置:首页 > 其它

【BZOJ 4448】 [Scoi2015]情报传递|树链剖分|树套树

2016-03-23 07:24 447 查看
更简单的 主席树在这 http://blog.csdn.net/sxb_201/article/details/50960373

我写的是 普通线段树套权值线段树 

虽然BZOJ过啦 但其实应该被卡一个点 

内存比着数据开 一点不能多 一点不能少 不然第六个点BZOJ会爆

没想到主席树 是我弱

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=200000+10;
int tot,g[MAXN*2],nnext[MAXN*2],num[MAXN*2];
int fa[MAXN],top[MAXN],son[MAXN],depth[MAXN],size[MAXN],loc[MAXN];
int n,m;
int team[MAXN],head,tail;
void Add(int x,int y)
{
tot++;
nnext[tot]=g[x];
g[x]=tot;
num[tot]=y;
}
void Lp(int rt)
{
depth[rt]=1;
team[++tail]=rt;
while(head<tail)
{
int x=team[++head];
for(int i=g[x];i;i=nnext[i])
{
int tmp=num[i];
depth[tmp]=depth[x]+1;
fa[tmp]=x;
team[++tail]=tmp;
}
}
for(int i=n;i>=1;i--)
{
int x=team[i];
size[x]=1;
for(int j=g[x];j;j=nnext[j])
{
int tmp=num[j];
size[x]+=size[tmp];
if(size[tmp]>size[son[x]]) son[x]=tmp;
}
}
loc[rt]=1;
top[rt]=rt;
for(int i=1;i<=n;i++)
{
int x=team[i];
int cnt=loc[x];
if(son[x]!=0)
{
loc[son[x]]=cnt+1;
cnt+=size[son[x]];
top[son[x]]=top[x];
}
for(int j=g[x];j;j=nnext[j])
{
int tmp=num[j];
if(tmp!=son[x])
{
loc[tmp]=cnt+1;
cnt+=size[tmp];
top[tmp]=tmp;
}
}
}
}
struct H
{
int L,R;
int sum;
}seg[MAXN*103];
int root[MAXN*4],rtc;
void Ins(int now,int L,int R,int x)
{
seg[now].sum++;
if(L==R) return ;
int mid=(L+R)/2;
if(x<=mid)
{
if(seg[now].L==0) seg[now].L=++rtc;
Ins(seg[now].L,L,mid,x);
}
else
{
if(seg[now].R==0) seg[now].R=++rtc;
Ins(seg[now].R,mid+1,R,x);
}
}
void Change(int now,int L,int R,int x,int y)
{
if(root[now]==0) root[now]=++rtc;
Ins(root[now],1,n,y);
if(L==R) return ;
int mid=(L+R)/2;
if(x<=mid) Change(now*2,L,mid,x,y);
else Change(now*2+1,mid+1,R,x,y);
}
int q(int now,int L,int R,int x)
{
if(now==0) return 0;
if(R<=x) return seg[now].sum;
int mid=(L+R)/2;
if(x<=mid) return q(seg[now].L,L,mid,x);
else return q(seg[now].L,L,mid,x)+q(seg[now].R,mid+1,R,x);
}
int Q(int now,int L,int R,int s,int t,int x)
{
if(s<=L&&R<=t)
{
return q(root[now],1,n,x);
}
int ans=0,mid=(L+R)/2;
if(s<=mid) ans+=Q(now*2,L,mid,s,t,x);
if(mid+1<=t) ans+=Q(now*2+1,mid+1,R,s,t,x);
return ans;
}
int ans1,ans2;
void QQ(int x,int y,int T)
{
ans1=ans2=0;
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]]) swap(x,y);
ans1+=loc[x]-loc[top[x]]+1;
ans2+=Q(1,1,n,loc[top[x]],loc[x],T);
x=fa[top[x]];
}
if(depth[x]<depth[y]) swap(x,y);
ans1+=loc[x]-loc[y]+1;
ans2+=Q(1,1,n,loc[y],loc[x],T);
}
int b[MAXN];
int main()
{
int rt,x,y,z,opt;
cin >>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
Add(x,i);
if(x==0) rt=i;
}
Lp(rt);
cin >>m;
for(int i=1;i<=m;i++)
{
scanf("%d",&opt);
if(opt==1)
{
scanf("%d %d %d",&x,&y,&z);
QQ(x,y,i-z-1);
printf("%d %d\n",ans1,ans2);
}
else
{
scanf("%d",&x);
if(!b[x])
{
Change(1,1,n,loc[x],i);
b[x]=true;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: