zoukankan      html  css  js  c++  java
  • luoguP3302 [SDOI2013]森林 主席树 启发式合并

    题目链接

    luoguP3302 [SDOI2013]森林

    题解

    本来这题树上主席树暴力启发式合并就完了
    结果把lca写错了...
    以后再也不这么写了
    复杂度(O(nlog^2n))

    "for(int i = 0;dad[x][i];++ i) dad[x][i+1] = dad[dad[x][i]][i]"
    

    De了两个多小时....QAQ

    代码

    #include<cstdio> 
    #include<cstring> 
    #include<algorithm> 
      
    inline int read() { 
        int x = 0,f = 1; 
        char c = getchar(); 
        while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar(); } 
        while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
        return x * f; 
    } 
      
    const int maxn = 100007; 
    struct NNnode {
        int v,next; 
    } edge[maxn << 2]; 
    int num = 0,head[maxn]; 
    inline void add_edge(int u,int v)  { 
        edge[++ num].v = v; edge[num].next = head[u]; head[u] = num; 
    } 
      
    int root[maxn],val[maxn],n,m,t,MX; 
    int tot = 0; 
    int ls[40000000],rs[40000000],cnt[40000000]; 
    void insert(int pre,int &now,int l,int r,int key) { 
        cnt[++ tot] = cnt[now]; now = tot; 
        ++ cnt[now]; 
        if(l == r) return ; 
        int mid = l + r >> 1; 
        ls[now] = ls[pre]; rs[now] = rs[pre]; 
        if(key <= mid) insert(ls[pre],ls[now],l,mid,key); 
        else insert(rs[pre],rs[now],mid + 1,r,key);  
    } 
      
    int query(int t1,int t2,int t3,int t4,int l,int r,int k) { 
        if (l == r) return l; 
        int mid = l + r >> 1; 
        int dtl = cnt[ls[t1]] + cnt[ls[t2]] - cnt[ls[t3]] - cnt[ls[t4]]; 
        if(k <= dtl) return query(ls[t1],ls[t2],ls[t3],ls[t4],l,mid,k); 
        else return query(rs[t1],rs[t2],rs[t3],rs[t4],mid + 1,r,k - dtl);  
    } 
      
    int root_num[maxn],siz[maxn], dep[maxn],dad[maxn][25]; 
    void dfs(int x) { 
        siz[x] = 1; 
        for(int i = 1;i < 20;++i) 
          dad[x][i] = dad[dad[x][i - 1]][i - 1]; 
        insert(root[dad[x][0]],root[x],1,MX,val[x]); 
        for(int i = head[x];i;i = edge[i].next) { 
            int v = edge[i].v; 
            if(v == dad[x][0]) continue; 
            root_num[v] = root_num[x]; 
            dad[v][0] = x; dep[v] = dep[x] + 1; 
            dfs(v); 
            siz[x] += siz[v]; 
        } 
    } 
    int LCA(int x,int y) { 
          
        if(dep[x] > dep[y]) std::swap(x,y); 
        for(int i = 19;i >= 0;i --) if(dep[dad[y][i]] >= dep[x]) y = dad[y][i]; 
        if(x == y) return x; 
        for(int i = 19;i >= 0;i --) if(dad[y][i] != dad[x][i]) y = dad[y][i],x = dad[x][i]; 
        return dad[x][0]; 
    } 
    int work_q(int x,int y,int k) { 
        int lca = LCA(x,y); 
        int F_lca = dad[lca][0]; 
        return query(root[x],root[y],root[lca],root[dad[lca][0]],1,MX,k); 
    } 
    void work_L(int x,int y) { 
        //printf("%d ***** %d
    ",x,y); 
        if(siz[root_num[x]] < siz[root_num[y]]) std::swap(x,y); 
        dad[y][0] = x; 
        siz[root_num[x]] += siz[root_num[y]]; 
        root_num[y] = root_num[x]; 
        dep[y] = dep[x] + 1; add_edge(x,y);add_edge(y,x);  
        dfs(y); 
    } 
    int b[maxn]; 
    void solve() { 
        tot = MX = 0; 
        n = read(),m = read(); t = read(); 
        for(int i = 1;i <= n;++ i) b[i] = val[i] = read(),MX = std::max(val[i],MX); 
        std::sort(b + 1,b + n + 1); 
        int len = std::unique(b + 1,b + n + 1) - b - 1; 
        for(int i = 1;i <= n;++ i) val[i] = std::lower_bound(b + 1,b + len + 1,val[i]) - b,MX = std::max(val[i],MX);
          
        for(int x,y,i = 1;i <= m;++ i) { 
            x = read(), y = read(); 
            add_edge(x,y) , add_edge(y,x);  
        } 
        for(int i = 1;i <= n;++ i) 
            if(!root_num[i]) root_num[i] = i,dep[i] = 1,dfs(i); 
        char opt[20]; 
        int lans = 0; 
        while(t --) { 
            scanf("%s",opt + 1) ; 
            if(opt[1] == 'Q')  { 
                int x = read() ^ lans,y = read() ^ lans, k = read() ^ lans; 
                //printf("%d **** %d *** %d *** &&&
    ",x,y,lans); 
                printf("%d
    ",lans = b[work_q(x,y,k)]); 
            } else { 
                int x = read() ,y = read() ; 
                x ^= lans,y ^= lans; 
                //printf("%d **** %d *** %d *** ***
    ",x,y,lans); 
                work_L(x,y); 
            } 
        } 
    } 
    int main() { 
        int testcase = read(); //whattttt the fucccck? 
        testcase = 1;  
        for(int i = 1;i <= testcase;++ i) solve();  
          
    } 
    
  • 相关阅读:
    手动启动log4j|nginx实现http https共存
    java.util.zip.ZipException: invalid LOC header (bad signature)
    Bean property 'transactionManagerBeanName' is not writable or has an invalid set
    rabbitmq启动异常table_attributes_mismatch
    nexus私服快速update index方法
    Spring boot ,dubbo整合异常
    如何编写无须人工干预的shell脚本
    Jenkins构建部署jar/war后,服务无法在后台持续运行的解决方案
    移动端CSS通用样式
    Spring bean的几种装配方式
  • 原文地址:https://www.cnblogs.com/sssy/p/9637228.html
Copyright © 2011-2022 走看看