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

来源:互联网 发布:马丁靴 知乎 编辑:程序博客网 时间:2024/06/05 23:43

传送门1
传送门2
写在前面:昨天一个小时能A三道题,今天三个小时A一道题
思路:比较裸的树链剖分,只不过是把边权值变成了点权值,开一个数组记录边和点的关系
注意:
1.比较最大值时ans设为-∞,不要设成0!
2.据本人经验,一个结构体有助于身体健康,两个就不行了……
代码:

#include<bits/stdc++.h>#define mul(x) (x<<1)#define Minn -0x7fffffffusing 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));        }    }}
0 0
原创粉丝点击