zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    Myeclipse安装svn插件
    Hudson+Maven+Svn搭建持续集成环境
    svn merge和branch分析
    Linux下安装subversion1.6.5和apache2
    C语言中,为什么字符串可以赋值给字符指针变量
    Loadrunner C 编程_1
    oracle解决多表关联分组查询问题
    学习英语
    使用 JMeter 完成常用的压力测试 [转]
    Jmeter零起点学习
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3082469.html
Copyright © 2011-2022 走看看