zoukankan      html  css  js  c++  java
  • [入门组模拟赛[难]]城市管理

    题目描述

    乐乐做了个梦,梦见自己当了国王。乐乐王国有 N 座城市(编号从 1~N,
    首都的编号为 1)。乐乐王国的道路构成树状结构:首都 1 与几个大城市相连,
    这几个大城市又通过道路与一些稍小的城市相连……严格地说,这 N 座城市构
    成一棵有根树(1 为树根),城市 i的管理区域为以 i 为根的子树。
    道路都是双向的。经过每条道路需要收费,从城市 A 到城市 B 的花费为 A
    到 B的简单路径上所有道路的费用之和(不妨称之为城市对(A, B)之间的花费)。
    显然,一棵树上任意两点之间的简单路径(即不能重复经过某个点的路径)是唯
    一的。
    由于物价飞涨,经过一番缜密的思考,乐乐决定重新规划自己国家的道路收
    费。具体来说,他要进行Q个操作,每个操作是如下两种类型:
    INC u v w
    ——表示 u 到 v的路径上,所有的道路的收费增加 w;
    ASK p
    ——表示询问城市 p的管理区域中,所有的“城市对”的花费之和。比如,
    城市 p的管理区域 (即以 p 为根子树) 中有城市 c1, c2, c3, …, cs (这里面包括 p) ,
    询问所有的城市对(c1, c2), (c1, c3), …, (c2, c3), …,(cs-1, cs)的花费之和。
    乐乐把这个问题交给你,快帮帮他吧!

    输入

    第一行输入两个正整数N,Q,分别表示城市的数目和操作的数目。
    接下来有 N – 1 行,第 i 行是两个正整数p[i], c[i],表示城市 p[i]是城市i 的
    父亲结点,且连接 p[i]和 i 的道路的初始收费为 c[i](1≤c[i]≤1000)。
    接下来有 Q行,每行是如下两种类型之一:
    INC u v w (u, v, w 都是整数,且 1≤u, v≤N, 0≤w≤1000,注意 u, v 可能相
    等)
    ASK p (p 是整数,且0≤p≤1000)
    意义如题目所述。

    输出

    对每个 ASK类型的操作,输出所求的答案。请你输出答案对 2018 取模后的
    结果。

    样例输入

    5 5
    1 1
    2 5
    1 2
    2 1
    INC 2 4 2
    INC 3 4 1
    ASK 2
    INC 2 5 3
    ASK 1

    样例输出

    14
    84

    提示

    对于 20%的数据,1≤Q, N≤200;
    对于 40%的数据,1≤Q, N≤5,000;
    对于 70%的数据,1≤Q, N≤50,000,且树的深度(即每个城市到首都经过
    的道路数目最大值)不会太大;
    对于 100%的数据,1≤Q, N≤50,000,树的深度不超过 10000,其他输入数
    据的范围在输入格式中已给出。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=50001;
    const int mod=2018;
    vector<int> e[N];
    int n,m,q,x,y,z,mid,val[N],fa[N],son[N],d[N],siz[N],l[N],r[N],top[N],num[N],len;
    char op[5];
    struct tree{
        int l,r,tag,siz1,siz2,sum1,sum2;
    }t[N*4];
    void dfs1(int k,int dep)
    {
        son[k]=0;
        d[k]=dep;
        siz[k]=1;
        for(int i=0;i<e[k].size();i++)
        {
            dfs1(e[k][i],dep+1);
            siz[k]+=siz[e[k][i]];
            if(siz[e[k][i]]>siz[son[k]])
                son[k]=e[k][i];
        }
    }
    void dfs2(int k,int tp)
    {
        l[k]=++len;
        num[len]=k;
        top[k]=tp;
        if(son[k])
            dfs2(son[k],tp);
        for(int i=0;i<e[k].size();i++)
        {
            if(e[k][i]==son[k]) continue;
            dfs2(e[k][i],e[k][i]);
        }
        r[k]=len;
    }
    void build(int k,int l,int r)
    {
        t[k].l=l,t[k].r=r;
        if(l==r)
        {
            t[k].siz1=siz[num[r]]%mod;
            t[k].siz2=1ll*siz[num[r]]*siz[num[r]]%mod;
            t[k].sum1=1ll*val[num[r]]*siz[num[r]]%mod;
            t[k].sum2=1ll*val[num[r]]*siz[num[r]]*siz[num[r]]%mod;
            return;
        }
        build(2*k,l,(l+r)/2);
        build(2*k+1,(l+r)/2+1,r);
        t[k].sum1=(t[2*k].sum1+t[2*k+1].sum1)%mod;
        t[k].sum2=(t[2*k].sum2+t[2*k+1].sum2)%mod;
        t[k].siz1=(t[2*k].siz1+t[2*k+1].siz1)%mod;
        t[k].siz2=(t[2*k].siz2+t[2*k+1].siz2)%mod;
    }
    void add(int k,int x,int y,int z)
    {
        if(x==t[k].l&&y==t[k].r)
        {
            if(x!=y) t[k].tag+=z;
            t[k].sum1=(t[k].sum1+1ll*t[k].siz1*z%mod)%mod;
            t[k].sum2=(t[k].sum2+1ll*t[k].siz2*z%mod)%mod;
            return;
        }
        if(t[k].tag)
        {
            add(2*k,t[2*k].l,t[2*k].r,t[k].tag);
            add(2*k+1,t[2*k+1].l,t[2*k+1].r,t[k].tag);
            t[k].tag=0;
        }
        if(y<=t[2*k].r) add(2*k,x,y,z);
        else if(x>=t[2*k+1].l) add(2*k+1,x,y,z);
        else
        {
            add(2*k,x,t[2*k].r,z);
            add(2*k+1,t[2*k+1].l,y,z);
        }
        t[k].sum1=(t[2*k].sum1+t[2*k+1].sum1)%mod;
        t[k].sum2=(t[2*k].sum2+t[2*k+1].sum2)%mod;
    }
    int ask(int k,int x,int y,int root)
    {
        if(x==t[k].l&&y==t[k].r)
            return (1ll*t[k].sum1*siz[root]%mod-t[k].sum2+mod)%mod;
        if(t[k].tag)
        {
            add(2*k,t[2*k].l,t[2*k].r,t[k].tag);
            add(2*k+1,t[2*k+1].l,t[2*k+1].r,t[k].tag);
            t[k].tag=0;
        }
        if(y<=t[2*k].r) return ask(2*k,x,y,root);
        if(x>=t[2*k+1].l) return ask(2*k+1,x,y,root);
        return (ask(2*k,x,t[2*k].r,root)+ask(2*k+1,t[2*k+1].l,y,root))%mod;
    }
    void change(int x,int y,int z)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(d[top[x]]<d[top[y]]) swap(x,y);
            add(1,l[top[x]],l[x],z);
            x=fa[top[x]];
        }
        if(x==y) return;
        if(d[x]>d[y]) swap(x,y);
        add(1,l[son[x]],l[y],z);
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=2;i<=n;i++)
        {
            scanf("%d%d",&fa[i],&val[i]);
            e[fa[i]].push_back(i);
        }
        dfs1(1,1);
        dfs2(1,1);
        build(1,1,len);
        for(int i=1;i<=q;i++)
        {
            scanf("%s",op);
            if(strcmp(op,"INC")==0)
            {
                scanf("%d%d%d",&x,&y,&z);
                change(x,y,z);
            }
            if(strcmp(op,"ASK")==0)
            {
                scanf("%d",&x);
                printf("%d
    ",(ask(1,l[x],r[x],x)%mod+mod)%mod);
            }
        }
        return 0;
    }
  • 相关阅读:
    [Luogu P3626] [APIO2009] 会议中心
    杭电 1869 六度分离 (求每两个节点间的距离)
    杭电 1874 畅通工程续 (求某节点到某节点的最短路径)
    最短路径模板
    杭电 2544 最短路径
    POJ 1287 Networking (最小生成树模板题)
    NYOJ 1875 畅通工程再续 (无节点间距离求最小生成树)
    POJ 2485 Highways (求最小生成树中最大的边)
    杭电 1233 还是畅通工程 (最小生成树)
    杭电 1863 畅通工程 (最小生成树)
  • 原文地址:https://www.cnblogs.com/LJA001162/p/13335626.html
Copyright © 2011-2022 走看看