• [Lydsy2017省队十连测]公路建设


    SOL:

     我们发现一棵生成树最多99条边,用线段树合并。

    #include<bits/stdc++.h>
    #define Mid (l+r>>1)
    #define ls no<<1,l,Mid
    #define rs no<<1|1,Mid+1,r
    #define N 110009
    using namespace std;
    struct Edge{
        int l,r,co;
    }e[N];
    int f[107];
    struct Node{
        int sum,a[107],to;
        void clear() {
            memset(a,0,sizeof a); sum=0; to=0;
        }
        int fa(int x){
            return f[x]==x?x:f[x]=fa(f[x]);
        }
        inline void join(int xx){
            static int u,v;
            u=fa(e[xx].l); v=fa(e[xx].r);
            if (u==v) return; 
            a[++to]=xx;
            f[u]=v;  sum+=e[xx].co;
        }
        void merge(Node X,Node& Y){
            static int ti,tj,op;
            clear();
            for (int i=1;i<107;i++) f[i]=i;
            ti=1; tj=1;
            while (X.a[ti]&&Y.a[tj]) 
                if (e[X.a[ti]].co<e[Y.a[tj]].co) join(X.a[ti++]);
                else join(Y.a[tj++]);
            while (X.a[ti]) join(X.a[ti++]);
            while (Y.a[tj]) join(Y.a[tj++]);
        }
    }t[N<<2],Ans;
    void build(int no,int l,int r){
        if (l==r) {
            t[no].sum=e[l].co;
            t[no].a[1]=l;   
            return;
        }
        build(no<<1,l,Mid); build(no<<1|1,Mid+1,r);
        t[no].merge(t[no<<1],t[no<<1|1]);
    }
    #define sight(x) ('0'<=x&&x<='9')
    inline void read(int &x){
        static char c;
        for (c=getchar();!sight(c);c=getchar());
        for (x=0;sight(c);c=getchar())x=x*10+c-48;
    }
    void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
    inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('
    '); }
    inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
    void que(int no,int l,int r,int L,int R){
        if (L<=l&&r<=R) {
            Ans.merge(Ans,t[no]); return;
        }
        if (L<=Mid) que(no<<1,l,Mid,L,R);
        if (R> Mid) que(no<<1|1,Mid+1,r,L,R);
    }
    int n,m,q,l,r;
    signed main () {
       read(n); read(m); read(q);
       for (int i=1;i<=m;i++) 
        read(e[i].l),read(e[i].r),read(e[i].co);
       build(1,1,m);
       while (q--) {
         read(l); read(r);
         Ans.clear();
         que(1,1,m,l,r);
         writeln(Ans.sum);
       }
       return 0;
    }
  • 相关阅读:
    Java并发之Thread类的使用
    剑指Offer
    总结下2017之前的几年
    解决一个特定的负载均衡下定时任务执行多次的问题
    《MYSQL》----字符串的复杂函数,检索的七-天-排-重
    科学计数法的转换
    小伙伴自言自语发给我的聊天记录,一句都看不懂
    记录下一个让我调了一天的失误
    记录一个从没见过的bug
    吐槽下
  • 原文地址:https://www.cnblogs.com/rrsb/p/9126900.html
Copyright © 2020-2023  润新知