• HDU4858 项目管理(分块)


    这道题展示了分块的强大,学到一手,虽然因为数据太过友好暴力也能过

    这道题边数多,直接遍历复杂度很高,大佬们想到了一种分摊复杂度的方法

    对于入度大于指定值例如(sqrt),这也是分块常用指定值的点,我们定义为重点

    否则为轻点,重点只和重点连,轻点和轻点连。这基于的原理是,重点的个数不超过sqrt个,并且轻点连的边数也不超过sqrt个

    对于每个点我们维护val也就是自身加的值,以及sum,周围点的和,对于查询,重点直接输出sum,而轻点进行遍历。

    正确的原因是,首先轻点肯定正确,因为是暴力,对于重点来说,所有对于轻点更新的大小,都会通过轻点连向重点的边更新到重点上

    同理,重点之间也能相互传递,所以求出sum就是答案。而轻点不能直接输出sum,因为对重点的更新无法传递到轻点,但是因为边数控制住了

    所以遍历的复杂度依旧不高。

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=2e5+20;
    typedef long long ll;
    int sum[N],val[N];
    int in[N];
    int st[N];
    vector<int> g[N];
    int n,m;
    struct node{
        int u,v;
    }s[N];
    void init(){
        int i;
        for(i=0;i<=n;i++){
            sum[i]=val[i]=in[i]=0;
            g[i].clear();
        }
    }
    int main(){
        int t;
        cin>>t;
        while(t--){
            int i;
            cin>>n>>m;
            init();
            for(i=1;i<=m;i++){
                scanf("%d%d",&s[i].u,&s[i].v);
                in[s[i].u]++;
                in[s[i].v]++;
            }
            int block=sqrt(n);
            for(i=1;i<=n;i++){
                if(in[i]>block)
                    st[i]=1;
            }
            for(i=1;i<=m;i++){
                int u=s[i].u;
                int v=s[i].v;
                if(st[u]){
                    if(st[v]){
                        g[u].push_back(v);
                        g[v].push_back(u);
                    }
                    else{
                        g[v].push_back(u);
                    }
                }
                else{
                    if(st[v]){
                        g[u].push_back(v);
                    }
                    else{
                        g[u].push_back(v);
                        g[v].push_back(u);
                    }
                }
            }
            int q;
            cin>>q;
            while(q--){
                int cmd;
                scanf("%d",&cmd);
                if(cmd){
                    int u;
                    scanf("%d",&u);
                    if(st[u]){
                        printf("%d
    ",sum[u]);
                    }
                    else{
                        int ans=0;
                        for(i=0;i<g[u].size();i++){
                            ans+=val[g[u][i]];
                        }
                        printf("%d
    ",ans);
                    }
                }
                else{
                    int u,v;
                    scanf("%d%d",&u,&v);
                    val[u]+=v;
                    for(i=0;i<g[u].size();i++){
                        int tmp=g[u][i];
                        sum[tmp]+=v;
                    }
                }
            }
        }
    }
    View Code
  • 相关阅读:
    VS2013中web项目中自动生成的ASP.NET Identity代码思考
    Identity角色管理五(添加用户到角色组)
    ASP.NET Core 3.0 使用gRPC
    ASP.NET CORE[练习7]Identity用户登录、最简单的登录验证
    dump解析入门用VS解析dump文件进行排障
    C#之Clone
    git push用法和常见问题分析
    python张量下标操作维度小于张量维度的情况
    Transformer position embedding 位置编码
    图graph的基础知识
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12559648.html
Copyright © 2020-2023  润新知