1. 程式人生 > >[Lydsy2017省隊十連測]公路建設

[Lydsy2017省隊十連測]公路建設

efi n) 線段樹合並 DC space char get #define ID

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(\n); } 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; }

[Lydsy2017省隊十連測]公路建設