HDU 4467 Graph(分块)

来源:互联网 发布:linux中的grep命令 编辑:程序博客网 时间:2024/05/22 14:18

题意:给出n个点,m条边,每个点都有一个颜色,黑色(用1表示)或白色(用0表示)。有两种操作,一种是询问所有边中满足边的两个点是00,01 or 11这三种情况的边的权值的和,另一种是修改某一点的颜色。

思路:如果直接暴力做的话,每次修改的复杂度达到O(m),考虑分块,对于度数小于lim的点,修改时暴力来做,

对于度数大于lim的点u,用sum[u][0]记录u向外连接颜色为零的边的权值和,然后将所有这些点建一个新图,这样每次只需要维护sum数组即可。这样的话修改和查询的复杂度都为O(sqrt(m))。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;//const int MAXN = 5000000 + 5;//const int INF = 0x3f3f3f3f;const LL mod = 1e9 + 7;int n;LL p, k;set<LL> s;LL fa[1000100];int Find(LL x) {    if(x != fa[x]) return fa[x] = Find(fa[x]);    return x;} int cnt[1001000];int main() {    //freopen("input.txt", "r", stdin);    cin >> p >> k;    s.insert(0);    LL ans = 1;    if(k==0) {        for(int i = 1; i < p; i++) ans = ans * p % mod;        cout << ans;        return 0;    }    for(int i = 0; i < p; i++) fa[i] = i;    for(int i = 0; i < p; i++) {        LL shit = k * i % p;        int x1 = Find(i), x2 = Find(shit);        fa[x1] = x2;    }    for(int i = 0; i < p; i++) {        int z = Find(i);        cnt[z]++;    }    for(int i = 1; i < p; i++)        if(cnt[i]) ans = ans * p % mod;    if(k == 1) ans = ans * p % mod;    cout << ans;    return 0;}


0 0
原创粉丝点击