bzoj 1036 树的统计

来源:互联网 发布:淘宝卖家工具 编辑:程序博客网 时间:2024/05/21 07:46

题目链接:点击打开链接

题目大意:有一棵树,30000个点,每个点有权值,接下来有20w个操作,分为三种,一是改变某个点的权值,二是询问从a到b的路径上的点的权值的最大值,三是询问a到b上点的权值和。

一道裸的树链剖分+线段树:

对于树上的路径问题,可以先进行轻重链划分,再用线段树解决。

轻重链剖分和点的重标号可以用dfs也可以用bfs


#include <iostream>#include <algorithm>#include <string.h>#include <vector>#include <cstdio>#define ll long long#define N 30005#define ls rt << 1#define rs rt << 1 | 1using namespace std;typedef struct{   int l,r,rt;   ll maxn,sum;}node;typedef struct{   int v;}next;vector<next>edge[N<<1];node Tree[N<<4];int weight[N];int sz[N],son[N],maxn[N],q[N],Index[N],dep[N],fa[N],top[N],w[N],id[N];//id用来记录当前的点属于哪个链void PushUp(int rt){     Tree[rt].maxn = max(Tree[ls].maxn,Tree[rs].maxn);     Tree[rt].sum = Tree[ls].sum + Tree[rs].sum;}void update(int p,int x,int rt){     if(p == Tree[rt].l && p ==Tree[rt].r){        Tree[rt].sum = x;        Tree[rt].maxn = x;        return ;     }     int mid;     mid = (Tree[rt].l + Tree[rt].r) >> 1;     if(p <= mid) update(p,x,ls);     else update(p,x,rs);     PushUp(rt);}void Build(int l,int r,int rt){     Tree[rt].l = l;     Tree[rt].r = r;     if(l == r){        Tree[rt].maxn = weight[Index[l]];        Tree[rt].sum = weight[Index[l]];        return ;     }     int mid;     mid = (l + r) >> 1 ;     Build(l,mid,ls);     Build(mid+1,r,rs);     PushUp(rt);}ll query(int op,int l,int r,int rt){     if(Tree[rt].l == l&&Tree[rt].r == r){        if(op == 0) return Tree[rt].maxn;        else if(op == 1) return Tree[rt].sum;     }     int mid;     mid =(Tree[rt].l+Tree[rt].r) >> 1;     if(r <= mid) return query(op,l,r,ls);     else if(l>mid) return query(op,l,r,rs);     else {        if(op == 0) return max(query(op,l,mid,ls),query(op,mid+1,r,rs));        else if(op == 1) return query(op,l,mid,ls)+query(op,mid+1,r,rs);     }}int lca(int x,int y){//重链的id一定小于轻边的id    while(id[x]!=id[y]){        if(id[x] > id[y]) swap(x,y);        y = fa[top[y]];    }    if(dep[x] > dep[y]) swap(x,y);    return x;}ll op1(int Lca,int a,int b){//对路径上的每一段连续的线段进行查询   ll ret = -6000000000;   while(1){    if(dep[top[a]] <=dep[Lca]){        ret = max(ret,query(0,w[Lca],w[a],1));        break;    }    else {        ret = max(ret,query(0,w[top[a]],w[a],1));        a = fa[top[a]];    }   }   while(1){    if(dep[top[b]] <= dep[Lca]){        ret = max(ret,query(0,w[Lca],w[b],1));        break;    }    else {        ret = max(ret,query(0,w[top[b]],w[b],1));        b = fa[top[b]];    }   }   return ret;}ll op2(int Lca,int a,int b){   ll ret = 0;   while(1){    if(dep[top[a]] <=dep[Lca]){        ret +=query(1,w[Lca],w[a],1);        break;    }    else {        ret += query(1,w[top[a]],w[a],1);        a = fa[top[a]];    }   }   while(1){    if(dep[top[b]] <=dep[Lca]){        ret += query(1,w[Lca],w[b],1);        break;    }    else {        ret += query(1,w[top[b]],w[b],1);        b = fa[top[b]];    }   }   ret -= query(1,w[Lca],w[Lca],1);   return ret;}void init(){      memset(maxn,-1,sizeof(maxn));      memset(sz,0,sizeof(sz));      memset(son,0,sizeof(son));}void bfs(int x){     int f,r,u,v,time,cnt;     f = r = 0;     q[r++] = x;     dep[x] = 1;     while(f<r){        u = q[f++];        for(int i = 0;i<edge[u].size();i++){            v = edge[u][i].v;            if(v!=fa[u]){                fa[v] = u;                dep[v] = dep[u] + 1;                q[r++] = v;            }        }     }     for(int i = r-1;i>=0; i--){        sz[fa[q[i]]] += ++sz[q[i]];        if(maxn[fa[q[i]]] < sz[q[i]]){            maxn[fa[q[i]]] = sz[q[i]];            son[fa[q[i]]] = q[i];        }     }     fa[1] = 1;     for(int i = 0;i < r; i++){        if(son[fa[q[i]]]!=q[i]){            top[q[i]] = q[i];        }        else{            top[q[i]] = top[fa[q[i]]];        }     }     cnt = 0;     f = 0;r = 1;     q[0] = x;     while(f<r){        u = q[f++];        if(top[u] == u) id[u] = ++cnt;        else{            id[u] = id[top[u]];        }        for(int i = 0;i<edge[u].size();i++){            v = edge[u][i].v;            if(v!=fa[u]) q[r++] = v;        }     }     f = 0;r = cnt = 1;     q[0] = x;     while(f<r){        u = q[f++];        v = u;        Index[cnt] = v;        w[v] = cnt++;        while(son[v]){            for(int i = 0;i<edge[v].size();i++){                if(edge[v][i].v!=fa[v]&&edge[v][i].v!=son[v]){                    q[r++] = edge[v][i].v;                }            }            v = son[v];            Index[cnt] = v;            w[v] = cnt++;        }     }}/*int dfs(int x,int f,int de){//dfs法     int s = 1,v,maxx = 0,tmp;     fa[x] = f;     dep[x] = de;     for(int i=0;i<edge[x].size();i++){            v = edge[x][i].v;            if(v!=f){            tmp = dfs(v,x,de+1);            if(tmp > maxx){                son[x] = v;                maxx = tmp;            }            s += tmp;            }     }     return sz[x] = s;}int Time = 1,cnt = 0;void dfs2(int x,int tp){     int v;     top[x] = tp;     Index[Time] = x;     w[x] = Time++;     if(son[x]) dfs2(son[x],tp);     for(int i = 0;i < edge[x].size();i++){        v = edge[x][i].v;        if(v!=fa[x]){        if(v != son[x]) dfs2(v,v);        }      }}void deal(int x){     int f,r,u,v;     f = 0;r = 1;     q[0] = x;     while(f<r){        u = q[f++];        if(top[u] == u)        id[u] = ++cnt;        else{            id[u] = id[top[u]];        }        for(int i = 0;i<edge[u].size();i++){            v = edge[u][i].v;            if(v!=fa[u]) q[r++] = v;        }     }}*/char opr[34];int main(){    init();    int n,a,b,q;    ll ans;    next tmp;    cin>>n;    for(int i = 0;i < n-1;i++){        scanf("%d%d",&a,&b);        tmp.v = b;        edge[a].push_back(tmp);        tmp.v = a;        edge[b].push_back(tmp);    }    for(int i = 1;i <= n; i++){        scanf("%d",&weight[i]);    }    bfs(1);    //dfs(1,1,1);    //dfs2(1,1);   // deal(1);    Build(1,n,1);    cin>>q;    int LCA;    for(int i = 0;i < q; i++){        scanf("%s",opr);        if(opr[0] == 'Q'){            scanf("%d%d",&a,&b);            LCA = lca(a,b);            if(opr[1] == 'M') ans = op1(LCA,a,b);            else ans = op2(LCA,a,b);            printf("%lld\n",ans);        }        else{            scanf("%d%d",&a,&b);            update(w[a],b,1);        }    }    return 0;}
加上一组数据
141 22 52 66 116 121 33 71 44 84 99 1313 144 105 9 7 1 13 10 8 6 2 5 11 12 3 48QMAX 11 12QSUM 11 12QSUM 5 10QMAX 5 10QMAX 11 14QSUM 11 14QMAX 11 5QSUM 11 5


0 0
原创粉丝点击