ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[SDOI2014]旅行(D12 树链剖分+动态开点)

2019-07-25 21:01:49  阅读:167  来源: 互联网

标签:颜色 D12 剖分 int top 树链 maxn 权值 id


题目描述

给一棵树,每个节点有一种颜色和权值,有四种操作:将一个节点颜色改变,讲一个节点权值改变,求一上路径上某种颜色的的点的权值和,求一条路径上某种颜色的点的最大权值

 

N,Q < =105 , C < =105

 

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时刻,城市的评级总是不大于104的正整数,且宗教值不大于C。

 

 

题解

一条路径上有多种颜色,不好同时维护,所以考虑一种暴力做法:树链剖分,对于每种颜色建一棵线段树,不是这个颜色在这棵线段树权值为0,因为查询是一种颜色就可以在一棵线段树上查,是可行的。

但如果将线段树开满的话是肯定会MLE的,考虑动态开点,初始会有nlgn个点,每次操作最多增加lgn个点,所以就可以保证空间。

要注意的是改变点权时,数组那里也要改,因为改颜色时要用到,不过也可以在改颜色的时候记录权值。

#include<bits/stdc++.h>
using namespace std;

const int maxn=100005;
int n,m;
int a[maxn],co[maxn];
int size[maxn],dep[maxn],fa[maxn],son[maxn];
int top[maxn],id[maxn],cnt;
int num,root[maxn],ls[maxn<<5],rs[maxn<<5],sum[maxn<<5],mx[maxn<<5];
vector<int>e[maxn];

template<class T>void read(T &x){
    x=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}

int max(int x,int y){return x>y ? x : y ;}

void dfs(int u){
    size[u]=1;
    for(unsigned int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==fa[u]) continue;
        fa[v]=u;
        dep[v]=dep[u]+1;
        dfs(v);
        size[u]+=size[v];
        if(size[son[u]]<size[v]) son[u]=v;
    }
}

void update(int rt){
    sum[rt]=sum[ls[rt]]+sum[rs[rt]];
    mx[rt]=max(mx[ls[rt]],mx[rs[rt]]);
}

void modify(int &rt,int l,int r,int pos,int val){
    if(!rt) rt=++num;
    if(l==r){
        mx[rt]=sum[rt]=val;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid) modify(ls[rt],l,mid,pos,val);
    else modify(rs[rt],mid+1,r,pos,val);
    update(rt);
}

void dfs(int u,int tp){
    id[u]=++cnt;
    top[u]=tp;
    modify(root[co[u]],1,n,cnt,a[u]);
    if(!son[u]) return ;
    dfs(son[u],tp);
    for(unsigned int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(v==fa[u]||v==son[u]) continue;
        dfs(v,v);
    }
}

int querysum(int rt,int l,int r,int a_l,int a_r){
    if(a_l<=l&&r<=a_r) return sum[rt];
    int ret=0,mid=(l+r)>>1;
    if(a_l<=mid) ret+=querysum(ls[rt],l,mid,a_l,a_r);
    if(mid<a_r) ret+=querysum(rs[rt],mid+1,r,a_l,a_r);
    return ret;
}

int querysum(int rt,int x,int y){
    int ret=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]>dep[top[y]]) swap(x,y);
        ret+=querysum(rt,1,n,id[top[y]],id[y]);
        y=fa[top[y]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ret+=querysum(rt,1,n,id[x],id[y]);
    return ret;
}

int querymax(int rt,int l,int r,int a_l,int a_r){
    if(a_l<=l&&r<=a_r) return mx[rt];
    int ans=0,mid=(l+r)>>1;
    if(a_l<=mid) ans=max(ans,querymax(ls[rt],l,mid,a_l,a_r));
    if(mid<a_r) ans=max(ans,querymax(rs[rt],mid+1,r,a_l,a_r));
    return ans;
}

int querymax(int rt,int x,int y){
    int ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]>dep[top[y]]) swap(x,y);
        ans=max(ans,querymax(rt,1,n,id[top[y]],id[y]));
        y=fa[top[y]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    ans=max(ans,querymax(rt,1,n,id[x],id[y]));
    return ans;
}

int main(){
    read(n);read(m);
    for(int i=1;i<=n;i++) read(a[i]),read(co[i]);
    for(int i=1;i<n;i++){
        int x,y;
        read(x);read(y);
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dep[1]=1;
    dfs(1);
    dfs(1,1);
    for(int i=1;i<=m;i++){
        char s[2];int x,y;
        scanf("%s",s);
        read(x);read(y);
        if(s[1]=='C'){//城市x改信y教 
            modify(root[co[x]],1,n,id[x],0);
            modify(root[y],1,n,id[x],a[x]);
            co[x]=y;
        }
        else if(s[1]=='W'){//城市x评级调为y 
            modify(root[co[x]],1,n,id[x],y);
            a[x]=y;///注意 
        }
        else if(s[1]=='S'){//x到y的评价总和 
            printf("%d\n",querysum(root[co[x]],x,y));
        }
        else {//x到y的评价最大值 
            printf("%d\n",querymax(root[co[x]],x,y));
        }
    }
}
View Code

 

标签:颜色,D12,剖分,int,top,树链,maxn,权值,id
来源: https://www.cnblogs.com/sto324/p/11246938.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有