#bzoj3394#雪后村庄(启发式合并 + 哈希)

3394: 雪后村庄

时间限制:1 Sec  内存限制: 512 MB

题目描述

 

输入


输出

输出q行,每行一个字符串“yes”或“no”(不包括引号)。

样例输入

2 4
3 4
1 2 3
2 3 2
2 4 4
1 2 3
1 3 2
2 3 2
3 4 4
4
1 3 3
1 3 2
1 4 3
3 4 4

样例输出

no
yes
no
no

提示




严格来说,这应该是我第一次写这样的哈希,确实不太会写。
这题很容易让人误入LCA的局里,尤其是感觉n=1的时候,LCA简直就是正解,但是无奈这里专门卡的就是LCA,肯定会超时。
缺乏意识,没想到可以通过离线处理来解决边权的查询问题。
贴一发大神题解,说得够清楚了。



介于个人能力蒟蒻,,哈希代码一直没过,但是出人意料的暴力强判居然过了(哈希代码已交由神犇拯救。。)

补充:在神犇帮助下,发现有个变量打错了,已经过了,但是还是没有暴力强判快。。。

Code:

无哈希,强判:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

typedef unsigned long long ULL;
typedef long long LL;

const int Maxn = 200005;
const int Maxm = 200005;
const int Max = 300005;
const int MOD = 1000000007;

struct LINE{
    int s, t, val, pos;
    bool operator < (const LINE & X) const{
        if(val == X.val)    return pos > X.pos;
        return val < X.val;
    }
}L[Maxm << 1];
struct node{
    int v, nxt;
}edge[Maxm << 1];

int Farm, N, All, cnt, Q;
int m[Maxn], fir[Maxn];
int Color[Maxm];
bool An[Maxm];
vector<int>Id[Maxn + 5];
vector<int>Cnt[Maxn + 5];

bool getint(int & num){
    char c; int flg = 1;    num = 0;
    while((c = getchar()) < '0' || c > '9'){
        if(c == '-')    flg = -1;
        if(c == -1) return 0;
    }
    while(c >= '0' && c <= '9'){
        num = num * 10 + c - 48;
        if((c = getchar()) == -1)   return 0;
    }
    num *= flg;
    return 1;
}

void addedge(int a, int b){
    edge[++ cnt].v = b, edge[cnt].nxt = fir[a], fir[a] = cnt;
}

bool Check(int u, int v){
    for(int i = 0; i < Farm; ++ i)
        if(Id[u][i] != Id[v][i])    return 0;
    return 1;
}

void exchange(int u, int col){
    int v = u % N, k = u / N;
    if(! v) v = N, -- k;
    Id[v][k] = col;
}

void Change(int u, int clr, int ff){
    exchange(u, clr);
    Color[u] = clr;
    for(int i = fir[u]; i; i = edge[i].nxt) if(edge[i].v != ff)
        Change(edge[i].v, clr, u);
}

void Together(int l, int r, int pos){
    int a = Color[l], b = Color[r];
    if(Cnt[pos][a] > Cnt[pos][b])
        Change(r, a, 0), Cnt[pos][a] += Cnt[pos][b], Cnt[pos][b] = 0;
    else Change(l, b, 0), Cnt[pos][b] += Cnt[pos][a], Cnt[pos][a] = 0;
    addedge(l, r), addedge(r, l);
}

int main(){
    //freopen("snow.in", "r", stdin);
    //freopen("snow.out", "w", stdout);
    getint(Farm), getint(N);
    All = Farm * N;
    for(int i = 1; i <= Farm; ++ i)
        getint(m[i]), m[i] += m[i - 1];
    Cnt[1].push_back(0);
    for(int i = 1; i <= N; ++ i){
        Color[i] = i;
        Id[i].push_back(Color[i]);
        Cnt[1].push_back(1);
    }
    for(int i = 2; i <= Farm; ++ i){
        Cnt[i].push_back(0);
        for(int j = 1; j <= N; ++ j){
            Color[(i - 1) * N + j] = j;
            Cnt[i].push_back(1);
            Id[j].push_back(j);
        }
    }
    for(int i = 1; i <= Farm; ++ i)
        for(int j = m[i - 1] + 1; j <= m[i]; ++ j)
            getint(L[j].s), getint(L[j].t), getint(L[j].val), L[j].pos = i;
    getint(Q);
    for(int i = 1; i <= Q; ++ i)
        getint(L[i + m[Farm]].s), getint(L[i + m[Farm]].t), getint(L[i + m[Farm]].val), L[i + m[Farm]].pos = Farm + i;
    sort(L + 1, L + 1 + Q + m[Farm]);
    for(int i = Q + m[Farm]; i; -- i){
        if(L[i].pos <= Farm){
            int l = (L[i].pos - 1) * N + L[i].s;
            int r = (L[i].pos - 1) * N + L[i].t;
            if(Color[l] != Color[r])
                Together(l, r, L[i].pos);
        }
        else {
            if(Check(L[i].s, L[i].t))  An[L[i].pos - Farm] = 1;
            else An[L[i].pos - Farm] = 0;
        }
    }
    for(int i = 1; i <= Q; ++ i)
        if(! An[i])   puts("no");
        else puts("yes");
    return 0;
}

Hash:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

typedef unsigned long long ULL;
typedef long long LL;

const int Maxn = 200005;
const int Maxm = 200005;
const int Max = 300005;
const int MOD = 1000000007;

struct LINE{
    int s, t, val, pos;
    bool operator < (const LINE & X) const{
        if(val == X.val)    return pos > X.pos;
        return val < X.val;
    }
}L[Maxm << 1];
struct node{
    int v, nxt;
}edge[Maxm << 1];

int Farm, N, All, cnt, Q;
int m[Maxn], fir[Maxn];
int Color[Maxm];
int Hash[Maxm], qmul[Maxm];
bool An[Maxm];
vector<int>Id[Maxn + 5];
vector<int>Cnt[Maxn + 5];

bool getint(int & num){
    char c; int flg = 1;    num = 0;
    while((c = getchar()) < '0' || c > '9'){
        if(c == '-')    flg = -1;
        if(c == -1) return 0;
    }
    while(c >= '0' && c <= '9'){
        num = num * 10 + c - 48;
        if((c = getchar()) == -1)   return 0;
    }
    num *= flg;
    return 1;
}

void addedge(int a, int b){
    edge[++ cnt].v = b, edge[cnt].nxt = fir[a], fir[a] = cnt;
}

void Pre(){
    int k = 7;
    qmul[0] = k;
    for(int i = 1; i < Farm; ++ i)    qmul[i] = 1ll * qmul[i - 1] * k % MOD;//就是这里,是Farm不是N
}

void exchange(int u, int col){
    int v = u % N, k = u / N;
    if(! v) v = N, -- k;
    Hash[v] = (Hash[v] - 1ll * Id[v][k] * qmul[k] % MOD + MOD) % MOD;
    Id[v][k] = col;
    Hash[v] = (Hash[v] + 1ll * Id[v][k] * qmul[k] % MOD) % MOD;
}

void Change(int u, int clr, int ff){
    exchange(u, clr);
    Color[u] = clr;
    for(int i = fir[u]; i; i = edge[i].nxt) if(edge[i].v != ff)
        Change(edge[i].v, clr, u);
}

void Together(int l, int r, int pos){
    int a = Color[l], b = Color[r];
    if(Cnt[pos][a] > Cnt[pos][b])
        Change(r, a, 0), Cnt[pos][a] += Cnt[pos][b], Cnt[pos][b] = 0;
    else Change(l, b, 0), Cnt[pos][b] += Cnt[pos][a], Cnt[pos][a] = 0;
    addedge(l, r), addedge(r, l);
}

int main(){
    //freopen("snow.in", "r", stdin);
    //freopen("snow.out", "w", stdout);
    getint(Farm), getint(N);
    Pre();
    for(int i = 1; i <= Farm; ++ i)
        getint(m[i]), m[i] += m[i - 1];
    Cnt[1].push_back(0);
    for(int i = 1; i <= N; ++ i){
        Color[i] = i;
        Id[i].push_back(Color[i]);
        Hash[i] = 1ll * i * qmul[0] % MOD;
        Cnt[1].push_back(1);
    }
    for(int i = 2; i <= Farm; ++ i){
        Cnt[i].push_back(0);
        for(int j = 1; j <= N; ++ j){
            Color[(i - 1) * N + j] = j;
            Cnt[i].push_back(1);
            Hash[j] = (Hash[j] + 1ll * j * qmul[i - 1] % MOD) % MOD;
            Id[j].push_back(j);
        }
    }
    for(int i = 1; i <= Farm; ++ i)
        for(int j = m[i - 1] + 1; j <= m[i]; ++ j)
            getint(L[j].s), getint(L[j].t), getint(L[j].val), L[j].pos = i;
    getint(Q);
    for(int i = 1; i <= Q; ++ i)
        getint(L[i + m[Farm]].s), getint(L[i + m[Farm]].t), getint(L[i + m[Farm]].val), L[i + m[Farm]].pos = Farm + i;
    sort(L + 1, L + 1 + Q + m[Farm]);
    for(int i = Q + m[Farm]; i; -- i){
        if(L[i].pos <= Farm){
            int l = (L[i].pos - 1) * N + L[i].s;
            int r = (L[i].pos - 1) * N + L[i].t;
            if(Color[l] != Color[r])
                Together(l, r, L[i].pos);
        }
        else {
            if(Hash[L[i].s] == Hash[L[i].t])  An[L[i].pos - Farm] = 1;
            else An[L[i].pos - Farm] = 0;
        }
    }
    for(int i = 1; i <= Q; ++ i)
        if(! An[i])   puts("no");
        else puts("yes");
    return 0;
}










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章