口袋妖怪黑攻略一周目图文_口袋妖怪黑攻略一周目图文

口袋妖怪黑攻略一周目图文_口袋妖怪黑攻略一周目图文西比拉先知系统题目描述【数据范围】n,m,Q≤3×105,y≤1000n,m,Q\leq3\times10^5,y\leq1000n,m,Q≤3×105,y≤1000具体做法与心路历程考试时一开始想的是怎么搞,先想了线

西比拉先知系统

题目描述

_8bbf41.png
【数据范围】

n , m , Q ≤ 3 × 1 0 5 , y ≤ 1000 n,m,Q \leq 3 \times 10^5 , y \leq 1000 n,m,Q3×105,y1000

具体做法与心路历程

考试时一开始想的是怎么搞,先想了线段树,后来发现不行,看数据范围 O ( n n ) O(n\sqrt{n}) O(nn
)
能过,于是想了莫队发现不好做,突然想起昨天提到了的根号分治,发现好像可行,于是想了一波。

具体做法

由于度数大于 2 m \sqrt{2m} 2m
的点不超过 2 m \sqrt{2m} 2m
个。分开考虑。对每个点记录一个 a n s [ i ] ans[i] ans[i] v a l [ i ] val[i] val[i]

考虑修改:

  • 所有 x x x只加自己: a n s [ x ] + = y , v a l [ x ] + = y ans[x]+=y,val[x]+=y ans[x]+=y,val[x]+=y和与 x x x相连的度数大于等于 2 m \sqrt{2m} 2m
    的点: a n s [ e [ i ] . t o ] + = y       ( d u [ e [ i ] . t o ] > = 2 m ) ans[e[i].to]+=y~~~~~(du[e[i].to]>= \sqrt{2m}) ans[e[i].to]+=y     (du[e[i].to]>=2m
    )

修改一次最多为 O ( 2 m ) O(\sqrt{2m}) O(2m
)

考虑查询:

  • 度数小于 2 m \sqrt{2m} 2m
    ,暴力枚举所有相连的边,答案为 ∑ v a l [ e [ i ] . t o ] \sum{val[e[i].to]} val[e[i].to] a n s [ x ] ans[x] ans[x]
  • 度数大于 2 m \sqrt{2m} 2m
    ,答案为 a n s [ x ] ans[x] ans[x]

对于第一种情况,查询一次最多为 O ( 2 m ) O(\sqrt{2m}) O(2m
)

对于第二种情况,查询一次为 O ( 1 ) O(1) O(1)

注意 这种题一定要用vector,用前向星一定会T!!!

C o d e \mathcal{Code} Code

/******************************* Author:galaxy yr LANG:C++ Created Time:2019年10月23日 星期三 08时44分36秒 *******************************/
#include<cstdio>
#include<algorithm>
#include<set>
#include<vector>
#include<cmath>

using namespace std;

struct IO{ 
   
    template<typename T>
    IO & operator>>(T&res)
    { 
   
        T q=1;char ch;
        while((ch=getchar())<'0' or ch>'9')if(ch=='-')q=-q;
        res=(ch^48);
        while((ch=getchar())>='0' and ch<='9') res=(res<<1)+(res<<3)+(ch^48);
        res*=q;
        return *this;
    }
}cin;

struct edge{ 
   
    int to,next;
    edge(int a=0,int b=0):to(a),next(b){ 
   }
};

struct Node{ 
   
    int u,v;
    Node(int a=0,int b=0):u(a),v(b){ 
   }
    bool operator<(const Node & p)  const
    { 
   
        if(u==p.u) return v<p.v;
        return u<p.u;
    }
};

const int maxn=3e5+10;
int n,m,q,du[maxn],head[maxn],cnt,LIM,ct,hd[maxn],a[maxn],b[maxn];
long long ans[maxn],val[maxn];
bool big[maxn];
vector<int>V[maxn],G[maxn];
set<Node>S;

inline void query_big(const int & x)
{ 
   
    printf("%lld\n",ans[x]);
}

inline void query_small(const int & x)
{ 
   
    long long res=ans[x];
    for(int i=0;i<V[x].size();i++)
        res+=val[V[x][i]];
    printf("%lld\n",res);
}

inline void modify(const int & x,const int & y)
{ 
   
    val[x]+=y,ans[x]+=y;
    for(int i=0;i<G[x].size();i++)
        ans[G[x][i]]+=y;
}

int main()
{ 
   
    //freopen("sibyl.in","r",stdin);
    //freopen("sibyl.out","w",stdout);
    cin>>n>>m>>q; LIM=300;
    int u,v;
    for(int i=1;i<=m;i++)
    { 
   
        cin>>u>>v;
        a[i]=u,b[i]=v;
        if(u==v) continue;
        if(u>v) swap(u,v);
        if(S.count(Node(u,v))) continue;
        S.insert(Node(u,v));
        du[u]++,du[v]++;
        V[u].push_back(v);
        V[v].push_back(u);
    }
    for(int i=1;i<=n;i++)
        if(du[i]>=LIM)
            big[i]=1;
    for(int i=1;i<=m;i++)
    { 
   
        if(big[a[i]])
            G[b[i]].push_back(a[i]);
        if(big[b[i]])
            G[a[i]].push_back(b[i]);
    }
    int opt,x,y;
    while(q--)
    { 
   
        cin>>opt>>x;
        if(opt==0)
        { 
   
            if(big[x])
                query_big(x);
            else
                query_small(x);
        }
        else
        { 
   
            cin>>y;
            modify(x,y);
        }
    }
    return 0;
}

今天的文章口袋妖怪黑攻略一周目图文_口袋妖怪黑攻略一周目图文分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/62846.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注