码迷,mamicode.com
首页 > 其他好文 > 详细

HYSBZ 1036 【树链剖分】

时间:2015-11-21 22:44:55      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:

思路:

裸裸的树链剖分....

树链剖分就是把一棵树分成若干重链和轻链...然后保证形成的线段树上每条链是连续存储的。然后这样就能用线段树进行维护了。

但是每次一定要保证是在同一条链里边....思路就是这样....

感觉最近越来越淡定了,题目卡住了也不怎么着急了,慢慢看代码...嗯...有点像学习的感觉了....

明天青岛理工的邀请赛要好好玩玩...

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m;
int myw[30100];
bool vis[30100];
int siz[30100],dep[30100],top[30100],fa[30100],son[30100],w[30100],fp[30100];
int totw;
char typ[20];
long long INF=0x3f3f3f3f3f;
struct edge
{
    int id;
    edge *next;
};
edge edges[30100<<1];
edge *adj[30100];
struct tr
{
    int s,e,maxx;
    long long sum;
};
tr tree[30100<<2];
void build(int k,int s,int e)
{
    tree[k].s=s;
    tree[k].e=e;
    if(s==e)
    {
        tree[k].sum=tree[k].maxx=myw[fp[s]];
        return;
    }
    int mid=(s+e)>>1;
    build(k<<1,s,mid);
    build(k<<1|1,mid+1,e);
    tree[k].maxx=max(tree[k<<1].maxx,tree[k<<1|1].maxx);
    tree[k].sum=tree[k<<1|1].sum+tree[k<<1].sum;
}
int ednum;
inline void AddEdge(int a,int b)
{
    edge *tmp;
    tmp=&edges[ednum++];
    tmp->id=b;
    tmp->next=adj[a];
    adj[a]=tmp;
}

void dfs1(int id,int mdep,int f)
{
    vis[id]=1;
    dep[id]=mdep;
    siz[id]=1;
    fa[id]=f;
    son[id]=0;
    int tmpsiz=-1;
    for(edge *it=adj[id]; it; it=it->next)
    {
        if(!vis[it->id])
        {
            dfs1(it->id,mdep+1,id);
            if(tmpsiz<siz[it->id])
            {
                tmpsiz=siz[it->id];
                son[id]=it->id;
            }
            siz[id]+=siz[it->id];
        }
    }
}
void dfs2(int id,int ase)
{
    vis[id]=1;
    top[id]=ase;
    w[id]=++totw;
    fp[totw]=id;
    if(son[id])
        dfs2(son[id],ase);
    for(edge *it=adj[id]; it; it=it->next)
    {
        if(!vis[it->id])
        {
            dfs2(it->id,it->id);
        }
    }
}
long long ans;
void querySum(int k,int s,int e)
{
    if(tree[k].e==e&&tree[k].s==s)
    {
        ans+=tree[k].sum;
        return;
    }
    int mid=(tree[k].s+tree[k].e)>>1;
    if(e<=mid)
    {
        querySum(k<<1,s,e);
    }
    else if(s>mid)
    {
        querySum(k<<1|1,s,e);
    }
    else
    {
        querySum(k<<1,s,mid);
        querySum(k<<1|1,mid+1,e);
    }
}
void qsum(int a,int b)
{
    int f1=top[a],f2=top[b];

    ans=0;
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            swap(f1,f2);
            swap(a,b);
        }
        querySum(1,w[f1],w[a]);
        a=fa[f1];
        f1=top[a];
    }
    if(dep[a]>dep[b])
        swap(a,b);
    querySum(1,w[a],w[b]);
    printf("%lld\n",ans);
}
void queryMax(int k,int s,int e)
{
    if(tree[k].e==e&&tree[k].s==s)
    {
        ans=max(ans,(long long)tree[k].maxx);
        return;
    }
    int mid=(tree[k].s+tree[k].e)>>1;
    if(e<=mid)
    {
        queryMax(k<<1,s,e);
    }
    else if(s>mid)
    {
        queryMax(k<<1|1,s,e);
    }
    else
    {
        queryMax(k<<1,s,mid);
        queryMax(k<<1|1,mid+1,e);
    }
}
void qmax(int a,int b)
{
    int f1=top[a],f2=top[b];
    ans=INF*(-1);
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            swap(f1,f2);
            swap(a,b);
        }
        queryMax(1,w[f1],w[a]);
        a=fa[f1];
        f1=top[a];
    }
    if(dep[a]>dep[b])
        swap(a,b);
    queryMax(1,w[a],w[b]);
    printf("%lld\n",ans);
}
void update(int k,int pos,int val)
{
    if(tree[k].s==tree[k].e)
    {
        tree[k].sum=tree[k].maxx=val;
        return;
    }
    int mid=(tree[k].s+tree[k].e)>>1;
    if(pos<=mid)
        update(k<<1,pos,val);
    else
        update(k<<1|1,pos,val);
    tree[k].sum=tree[k<<1|1].sum+tree[k<<1].sum;
    tree[k].maxx=max(tree[k<<1].maxx,tree[k<<1|1].maxx);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(siz,0,sizeof(siz));
        memset(vis,0,sizeof(vis));
        memset(son,0,sizeof(son));
        fa[1]=0;
        totw=0;
        ednum=0;
        for(int i=1;i<=n;i++)
        {
            adj[i]=NULL;
        }
        for(int i=1; i<n; i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            AddEdge(a,b);
            AddEdge(b,a);
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&myw[i]);
        }
        dfs1(1,1,0);
        memset(vis,0,sizeof(vis));
        dfs2(1,1);
        build(1,1,totw);
        scanf("%d",&m);
        for(int i=1; i<=m; i++)
        {
            int a,b;
            scanf("%s%d%d",typ,&a,&b);
            if(typ[3]==X)
            {
                qmax(a,b);
            }
            else if(typ[3]==M)
            {
                qsum(a,b);
            }
            else if((typ[3]==N))
            {
                update(1,w[a],b);
            }
        }
    }
}
/*
8
1 2
1 4
2 3
3 8
5 6
7 5
2 5
3 7 6 5 8 2 1 0
1000
*/

 

HYSBZ 1036 【树链剖分】

标签:

原文地址:http://www.cnblogs.com/tun117/p/4984861.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!