[Wc2006]水管局长数据加强版 LCA&RMQ

参考论文: 郭华阳《RMQ与LCA问题》 的解法.

通过构建最小生成树,然后转换成 寻找最近公共祖先来求解, 逆序处理询问,将删除改成添加边.

代码在BZOJ上WA了.暂时未找到原因, 先放着... 不过有看到用splay, 动态树等做的..

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
const int N = (int)1e5+10;
const int M = (int)1e6+10;
const int maxn = 5*N;
int n, m, Q_num;
struct node{
    int a, b, t;
    bool operator < (const node &tmp) const{
        return t < tmp.t;
    }
}edge[M];
struct Query{
    int k,a,b;
}Q[N];

map< pair<int,int>, int > mp;
vector<int> S[2*N+10];

int getint(){
    char ch = getchar();
    for(; ch > '9' || ch < '0'; ch = getchar() );
    int tmp = 0;
    for(; ch > '0' && ch < '9'; ch = getchar() )
        tmp = tmp*10 + ch - '0';
    return tmp;
}

int st[maxn], top;
bool vis[M];

int find(int x){
    return st[x] == x ? x : find(st[x]);
}

void debug(){
    printf("n = %d, m = %d, Q_num = %d\n", n, m, Q_num );
    printf("Edge:\n");
    for(int i = 0; i < m; i++)
        printf("(%d,%d,t=%d)\n", edge[i].a, edge[i].b, edge[i].t );
    printf("Query:\n");
    for(int i = 0; i < Q_num; i++)
        printf("k=%d,(%d,%d)\n", Q[i].k, Q[i].a, Q[i].b );

}
void input(){
    n = getint(); m = getint(); Q_num = getint();
        
    for(int i = 0; i < m; i++){ // Edge infomation
        edge[i].a = getint();
        edge[i].b = getint();
        edge[i].t = getint();
    }
    for(int i = 0; i < Q_num; i++){ // Query 
        Q[i].k = getint();
        Q[i].a = getint();
        Q[i].b = getint();
    }
    sort( edge, edge+m ); // sort by t desc
    for(int i = 0; i < m; i++) // index
        mp[ make_pair( edge[i].a, edge[i].b ) ] = 
            mp[ make_pair( edge[i].b, edge[i].a ) ] = i;
    for(int i = 0; i < Q_num; i++){
        if( Q[i].k == 2 )    
            vis[ mp[make_pair(Q[i].a, Q[i].b)] ] = true;    
    }    
//    for(int i = 0; i < m; i++)
//        printf("%d ", vis[i] ); puts("");
}

int val[maxn];
int pos[maxn], dep[maxn], vec[maxn], idx;
int dp[maxn][50];

void dfs(int u,int d){
    dep[++idx] = d; vec[idx] = u;    
    if( pos[u] == -1 ) pos[u] = idx;
    dep[idx] = d;
    for(int i = 0; i < (int)S[u].size(); i++){
        dfs( S[u][i], d+1 );    
        dep[++idx] = d;    vec[idx] = u;    
    }
}

void print(){
    printf("Top = %d\n", top);
    for(int i = 1; i <= top; i++) printf("pos[%d] = %d, val[%d] = %d\n", i, pos[i], i, val[i]);

    printf("idx = %d\n", idx);
    for(int i = 1; i <= idx; i++)
        printf("i = %d, vec[%d] = %d, dep[%d] = %d\n", i, i, vec[i], i, dep[i] );    

}
void predeal(){
    for(int i = 0; i < 2*n+10; i++)
        st[i] = i, S[i].clear();    
    top = n;
    for(int i = 0; i < m; i++){
        if( vis[ mp[ make_pair( edge[i].a, edge[i].b )  ] ] == false ){
            int a = edge[i].a, b = edge[i].b, t = edge[i].t;
            int x = find(a), y = find(b);    
        //    printf("(%d,%d): x = %d, y = %d\n",a,b, x, y );    
            if( x != y ){
                st[x] = st[y] = ++top;
                val[top] = t;
                S[top].push_back(x), S[top].push_back(y);    
            }
        }    
    }

    for(int i = 1; i <= top; i++) 
        pos[i] = -1; 
    idx = 0;
    dfs( top, 0 );    

    //print();
    // init RMQ
    for(int i = 1; i <= idx; i++)
        dp[i][0] = i;
    for(int j = 1; (1<<j) <= idx; j++){
        for(int i = 1; i+(1<<j)-1 <= idx; i++){
            // dp[i][j] = min( dp[i][j-1], dp[i+(1<<(j-1))][j-1] );
            if( dep[ dp[i][j-1] ] < dep[ dp[i+(1<<(j-1))][j-1] ] )
                dp[i][j] = dp[i][j-1];
            else dp[i][j] = dp[i+(1<<(j-1))][j-1];
        }    
    }
}
int RMQ_find(int l,int r){
    int d = r-l+1, k = 0;
    while( (1<<(k+1)) < d ) k++;
//    printf("RMQ: k = %d\n", k );
//    printf("RMQ: L = %d, R = %d\n", dp[l][k] , dp[r-(1<<k)+1][k] );
    if( dep[ dp[l][k] ] < dep[ dp[r-(1<<k)+1][k] ] ) return dp[l][k];
    return dp[ r-(1<<k)+1 ][k];
}

int ans[M], ans_cnt;

void solve(){
    int ans_cnt = 0;
    predeal();
    for(int i = Q_num-1; i >= 0; i-- ){ 
        if( Q[i].k == 1 ){
            int l = pos[ Q[i].a ], r = pos[ Q[i].b ];
        //    printf("(a=%d,b=%d),(l=%d,r=%d)\n", Q[i].a, Q[i].b, l, r);    
            if( l > r ) swap( l, r );
            int pt = RMQ_find(l,r);  //printf("pt = %d\n", pt );    
            ans[ ans_cnt++ ] = val[ vec[pt] ];
        }
        else{
            // Q[i].k == 2 
            vis[ mp[ make_pair( Q[i].a,Q[i].b ) ] ] = false;
            predeal(); // restructrue the min genaration tree
        }
    //    puts("******************************************************");    
    }
    for(int i = ans_cnt-1; i >= 0; i-- ){
        printf("%d\n", ans[i] );    
    }
}

int main(){
    freopen("1.in","r",stdin);

    input();
    solve();

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/yefeng1627/p/3082469.html