• [机房测试]弟娃


    Description

    给定一棵树,每次新加一条链。可以选择一个点,如果该点到该链的最短路恰好结束于这条链的端点,就会产生一个贡献。现在每新增一条链都需要询问如何选点能使贡献和最大,输出最大值。

    Solution

    比较签到,前半个小时就写了。

    同时维护每个点的答案,可以分为三种情况(假设 (dep_x)geq(dep_y))。

    1. (x=y),直接全局加一。

    2. (y) 不是 (x) 的祖先,容易发现 (x)(y) 子树内的所有点答案加一。

    3. (y)(x) 的祖先,答案加一的就是 (x) 的子树和 (y) 除去包含 (x) 的那个儿子的子树的其他点。

    容易发现可以直接倍增找儿子,线段树维护答案。

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
     
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
     
    const int N=3e5+7;
     
    struct Node{
        int mx,tag;
    }t[N<<2];
     
    int head[N],fa[N][19],in[N],sz[N],dep[N];
     
    struct E{
        int next,to;
    }e[N<<1];
     
    inline void add(int id,int to){
        static int cnt=0;
        e[++cnt]=(E){head[id],to};
        head[id]=cnt;
        e[++cnt]=(E){head[to],id};
        head[to]=cnt;
    }
     
    void dfs(int u){
        static int timer=0;
        dep[u]=dep[fa[u][0]]+1;
        sz[u]=1,in[u]=++timer;
        for(int i=1;i<19;i++)
            fa[u][i]=fa[fa[u][i-1]][i-1];
        for(int i=head[u];i;i=e[i].next){
            const int v=e[i].to;
            if(v==fa[u][0]) continue;
            fa[v][0]=u,dfs(v),sz[u]+=sz[v];
        }
    }
     
    #define lid id<<1
    #define rid id<<1|1
     
    inline void Add(int id,int v){t[id].tag+=v,t[id].mx+=v;}
    inline void pd(int id){
        if(t[id].tag)
            Add(lid,t[id].tag),Add(rid,t[id].tag);
        t[id].tag=0;
    }
     
    int L,R,op;
    void modify(int id,int lf,int rf){
        if(L<=lf&&rf<=R){Add(id,op);return;}
        int mid=(lf+rf)>>1; pd(id);
        if(L<=mid) modify(lid,lf,mid);
        if(R>mid) modify(rid,mid+1,rf);
        t[id].mx=max(t[lid].mx,t[rid].mx);
    }
     
    inline bool check(int u,int v){
        for(int i=18;~i;i--)
            if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
        return (u==v);
    }
     
    int main(){
        int n=read(),m=read();
        for(int i=1;i<n;i++) add(read(),read());
        dfs(1); int ret=0;
        while(m--){
            int x=read(),y=read();
            if(x!=y){
                if(dep[x]<dep[y]) swap(x,y);
                if(check(x,y)){
                    int now=x; ret++;
                    for(int i=18;~i;i--)
                        if(dep[fa[now][i]]>dep[y]) now=fa[now][i];
                    op=-1,L=in[now],R=in[now]+sz[now]-1,modify(1,1,n);
                    op=1,L=in[x],R=in[x]+sz[x]-1,modify(1,1,n);
                }else{
                    op=1;
                    L=in[x],R=in[x]+sz[x]-1,modify(1,1,n);
                    L=in[y],R=in[y]+sz[y]-1,modify(1,1,n);
                }
            }else ret++;
            printf("%d
    ",ret+t[1].mx);
        }
    }
    
  • 相关阅读:
    MVC4笔记 @functions @model @using
    NET平台4.0 发布网站流程及出错总结
    C#读写txt文件的方法
    jQuery Validate验证框架详解(转)
    用C#写的读写CSV文件
    devexpress 数据导入(gridcontrol 导出 csv)
    DevExpress XtraGrid 数据导出导入Excel
    DevExpress 表中数据导出
    DevExpress 重编译 替换强命名 修改源码
    Delphi 的运算符列表
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15377019.html
Copyright © 2020-2023  润新知