您的位置:首页 > 其它

【codevs2460】【BZOJ1036】树的统计count,第一次的树链剖分

2016-03-16 21:05 369 查看
传送门1

传送门2

写在前面:昨天一个小时能A三道题,今天三个小时A一道题

思路:比较裸的树链剖分,只不过是把边权值变成了点权值,开一个数组记录边和点的关系

注意:

1.比较最大值时ans设为-∞,不要设成0!

2.据本人经验,一个结构体有助于身体健康,两个就不行了……

代码:

#include<bits/stdc++.h>
#define mul(x) (x<<1)
#define Minn -0x7fffffff
using namespace std;
int n,q,tot,x,y,cnt;
int first[30010],pre[30010];
char ch[10];
struct point
{
int top,siz,dep,fa,son,w,hash;
}a[30010];
struct os
{
int u,v,next;
}e[60010];
struct node
{
int sum,maxn;
}tree[120010];
void add(int x,int y)
{
e[++tot].u=x;
e[tot].v=y;
e[tot].next=first[x];
first[x]=tot;
}
void dfs1(int now)
{
a[now].siz=1;
for (int i=first[now];i;i=e[i].next)
if (e[i].v!=a[now].fa)
{
a[e[i].v].fa=now;
a[e[i].v].dep=a[now].dep+1;
dfs1(e[i].v);
if (a[e[i].v].siz>a[a[now].son].siz)
a[now].son=e[i].v;
a[now].siz+=a[e[i].v].siz;
}
}
void dfs2(int now,int tp)
{
a[now].hash=++cnt;
a[now].top=tp;
pre[cnt]=now;
if (a[now].son)
dfs2(a[now].son,tp);
for (int i=first[now];i;i=e[i].next)
if (e[i].v!=a[now].son&&e[i].v!=a[now].fa)
dfs2(e[i].v,e[i].v);
}
void build(int now,int begin,int end)
{
if (begin==end) {tree[now].sum=tree[now].maxn=a[pre[begin]].w;return;}
int mid=(begin+end)>>1;
build(mul(now),begin,mid);
build(1+mul(now),mid+1,end);
tree[now].maxn=max(tree[mul(now)].maxn,tree[1+mul(now)].maxn);
tree[now].sum=tree[mul(now)].sum+tree[1+mul(now)].sum;
}
void update(int now,int begin,int end,int pos,int num)
{
if (begin==end) {tree[now].sum=tree[now].maxn=num;return;}
int mid=(begin+end)>>1;
if (pos<=mid) update(mul(now),begin,mid,pos,num);
else update(1+mul(now),mid+1,end,pos,num);
tree[now].maxn=max(tree[mul(now)].maxn,tree[1+mul(now)].maxn);
tree[now].sum=tree[mul(now)].sum+tree[1+mul(now)].sum;
}
int get_max(int now,int begin,int end,int l,int r)
{
if (l<=begin&&end<=r) return tree[now].maxn;
int mid=(begin+end)>>1,ans=Minn;
if (l<=mid) ans=max(ans,get_max(mul(now),begin,mid,l,r));
if (r>mid) ans=max(ans,get_max(mul(now)+1,mid+1,end,l,r));
return ans;
}
int get_sum(int now,int begin,int end,int l,int r)
{
if (l<=begin&&end<=r) return tree[now].sum;
int mid=(begin+end)>>1,ans=0;
if (l<=mid) ans+=get_sum(mul(now),begin,mid,l,r);
if (r>mid) ans+=get_sum(mul(now)+1,mid+1,end,l,r);
return ans;
}
int solve1(int l,int r)
{
int ans=Minn,f1=a[l].top,f2=a[r].top;
while (f1!=f2)
{
if (a[f1].dep<a[f2].dep) swap(f1,f2),swap(l,r);
ans=max(ans,get_max(1,1,cnt,a[f1].hash,a[l].hash));
l=a[f1].fa;f1=a[l].top;
}
if (a[l].dep>a[r].dep) swap(l,r);
return max(ans,get_max(1,1,cnt,a[l].hash,a[r].hash));
}
int solve2(int l,int r)
{
int ans=0,f1=a[l].top,f2=a[r].top;
while (f1!=f2)
{
if (a[f1].dep<a[f2].dep) swap(f1,f2),swap(l,r);
ans+=get_sum(1,1,cnt,a[f1].hash,a[l].hash);
l=a[f1].fa;f1=a[l].top;
}
if (a[l].dep>a[r].dep) swap(l,r);
return ans+get_sum(1,1,cnt,a[l].hash,a[r].hash);
}
main()
{
scanf("%d",&n);
for (int i=1;i<n;i++)
scanf("%d%d",&x,&y),
add(x,y),
add(y,x);
for (int i=1;i<=n;i++) scanf("%d",&a[i].w);
dfs1(1);
dfs2(1,1);
build(1,1,cnt);
scanf("%d",&q);
while (q--)
{
scanf("%s",ch);
scanf("%d%d",&x,&y);
if (ch[0]=='C')
update(1,1,cnt,a[x].hash,y);
else
{
if (ch[1]=='M') printf("%d\n",solve1(x,y));
else printf("%d\n",solve2(x,y));
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: