#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;
}










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