Codeforces Round #457 (Div. 2) E

赛后补题: 树链剖分套区间更新线段树 注意lca的求法
官方题解:http://codeforces.com/blog/entry/57223

code:



#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<string>
#include<queue>

using namespace std;

const int maxn = 100055;
const int mod = 1e9+7;
typedef long long ll;

#define lson rt<<1
#define rson rt<<1|1
#define inf 1<<30

int root,sum,num;
int pos[maxn];
int top[maxn];
int Size[maxn];
int p[maxn];
int id[maxn];
int son[maxn];
int d[maxn];
ll val[maxn];
int la[maxn];

vector<int> G[maxn];

struct node{
    int l,r;
    ll val;
    ll lazy;
}rmq[maxn<<2];

void init(){
    memset(son,-1,sizeof(son));
    memset(p,-1,sizeof(p));
    root=1;
}

void dfs1(int u,int fa,int step){
    d[u]=step;
    p[u]=fa;
    Size[u]=1;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v==fa) continue;
        dfs1(v,u,step+1);
        Size[u]+=Size[v];
        if(son[u]==-1||Size[v]>Size[son[u]]) son[u]=v;
    }
}

void dfs2(int u,int tp){
//    cout<<u<<' '<<tp<<endl;
    top[u]=tp;
    id[u]=la[u]=++num;
    pos[id[u]]=u;
    if(son[u]==-1) return ;
    dfs2(son[u],tp);
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(v!=son[u]&&v!=p[u]){
            dfs2(v,v);
        }
    }
    la[u]=num;
}

int lca(int u,int v){
//    cout<<u<<' '<<v<<endl;
    while(top[u]!=top[v]){
        if(d[top[u]]<d[top[v]]) swap(u,v);
        u=p[top[u]];
    //    cout<<u<<' '<<v<<endl;
    }
    return d[u]<d[v]?u:v;
}

int LCA(int u,int v){
    int a=lca(u,v);
    int b=lca(root,u);
    int c=lca(root,v);
    if(d[a]<d[b]) swap(a,b);
    if(d[a]<d[c]) swap(a,c);
    return a;
}

int nearlca(int u,int v){
    if(d[u]>d[v]) swap(u,v);
    if(top[u]==top[v]) return pos[id[u]+1];
    while(top[u]!=top[v]){
        if(d[top[u]]>d[top[v]]) swap(u,v);
        if(p[top[v]]==u) break;
        else v=p[top[v]];
    }
    if(top[u]==top[v]) return pos[id[u]+1];
    else return top[v];
}

void Pushup(int rt){
    rmq[rt].val=rmq[lson].val+rmq[rson].val;
}

void Pushdown(int rt){
    int l=rmq[rt].l;
    int r=rmq[rt].r;
    int m=(l+r)>>1;
    if(rmq[rt].lazy!=0){
        ll c=rmq[rt].lazy;
        rmq[lson].lazy+=c;
        rmq[rson].lazy+=c;
        rmq[lson].val+=(ll)(m-l+1)*c;
        rmq[rson].val+=(ll)(r-m)*c;
        rmq[rt].lazy=0;
    }
}

void build(int l,int r,int rt){
    rmq[rt].l=l;
    rmq[rt].r=r;
    rmq[rt].lazy=0;
    if(l==r){
        rmq[rt].val=val[pos[l]];
        return;
    }
    int m=(l+r)>>1;
    build(l,m,lson);
    build(m+1,r,rson);
    Pushup(rt);
}

void update(int rt,int L,int R,int c){
    int l=rmq[rt].l;
    int r=rmq[rt].r;
    if(L<=l&&r<=R){
        rmq[rt].val+=(ll)(r-l+1)*c;
        rmq[rt].lazy+=c;
        return ;
    }
    Pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m) update(lson,L,R,c);
    if(m<R) update(rson,L,R,c);
    Pushup(rt);
}

ll query(int rt,int L,int R){
    int l=rmq[rt].l;
    int r=rmq[rt].r;
    if(L<=l&&r<=R) return rmq[rt].val;
    Pushdown(rt);
    int m=(l+r)>>1;
    ll ret=0;
    if(L<=m) ret+=query(lson,L,R);
    if(m<R) ret+=query(rson,L,R);
    return ret;
}

void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}

ll Query(int x){
    return query(1,id[x],la[x]);
}

void Update(int x,int c){
    update(1,id[x],la[x],c);
}

bool ini(int x,int y){
    if(id[x]>=id[y]&&id[x]<=la[y]) return true;
    return false;
}

int main(){
//    freopen("in.txt","r",stdin);
    init();
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++){
        cin>>val[i];
    }
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add_edge(u,v);
    }
    dfs1(1,-1,0);
    dfs2(1,1);
    build(1,num,1);

/*
    for(int i=1;i<=n;i++){
        cout<<i<<' '<<id[i]<<' '<<la[i]<<endl;
    }
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++){
            cout<<i<<' '<<j<<' '<<nearlca(i,j)<<endl;
        }

*/
    while(q--){
        int k;
        scanf("%d",&k);
        if(k==1){
            int v;
            scanf("%d",&v);
            root=v;
        }else if(k==2){
            int u,v,x;
            scanf("%d%d%d",&u,&v,&x);
            int in_cnt=0;
            int rt;
            if(ini(u,root)) in_cnt++;
            if(ini(v,root)) in_cnt++;
            if(in_cnt==1) rt=root;
            else if(in_cnt==2) rt=lca(u,v);
            else rt=LCA(u,v);
            if(rt==root){
                Update(1,x);
            }else if(ini(rt,root)){
                Update(rt,x);
            }else if(ini(root,rt)){
                Update(1,x);
                int y=nearlca(root,rt);
                Update(y,-x);
            }else {
                Update(rt,x);
            }
        }else if(k==3){
            int v;
            scanf("%d",&v);
            ll ans;
            if(v==root){
                ans=Query(1);
            }else if(ini(v,root)){
                ans=Query(v);
            }else if(ini(root,v)){
                ans=Query(1);
                int x=nearlca(root,v);
                ans-=Query(x);
            }else {
                ans=Query(v);
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值