[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

 

你可能感兴趣的:(MQ)