红蓝图 kruskal重构树+dfs序+线段树合并

红蓝图 kruskal重构树+dfs序+线段树合并

题解:

如果不会kruskal重构树,建议先写 D. Graph and Queries 并查集+线段树+kruskal重构树

  • 首先对查询按照 t 从大到小排序,然后按照权值从大到小建一棵kruskal重构树,然后dfs求出每一个节点的dfs序,顺便求出每一个询问节点的子树节点。
  • 对于每一个节点都建一棵动态开点的线段树,然后对查询按照 t 从小到大排序,边建线段树边输出询问。
#include <bits/stdc++.h>
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
const int maxn = 1e6+10;
int a[maxn],b[maxn],c[maxn];
struct node{
    int x,t,id;
    node(int x=0,int t=0,int id=0):x(x),t(t),id(id){}
}e[maxn];
bool cmp(node a,node b){
    return a.t<b.t;
}
int head[maxn],to[maxn<<1],nxt[maxn<<1],cnt;
void add(int u,int v){
    // printf("u = %d v = %d
", u,v);
    ++cnt,to[cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
    ++cnt,to[cnt]=u,nxt[cnt]=head[v],head[v]=cnt;
}
int f[maxn],now;
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}

void unite(int x,int y){
    x = find(x),y = find(y);
    if(x == y) return ;
    ++now,add(x,now),add(y,now);
    f[now] = f[x] = f[y] = now;
}
int subTree[maxn],el[maxn],er[maxn],tot;
void dfs(int u,int pre){
    el[u] = ++tot;
    for(int i=head[u];i;i=nxt[i]){
        int v = to[i];
        if(v == pre) continue;
        dfs(v,u);
    }
    er[u] = tot;
}
int root[maxn],sum[maxn<<2],sz,lc[maxn<<2],rc[maxn<<2];
void push_up(int id){
    sum[id] = sum[lc[id]] + sum[rc[id]];
}
void update(int &id,int l,int r,int pos){
    if(!id) id = ++sz;
    if(l==r){
        sum[id] = 1;
        return ;
    }
    int mid = (l+r)>>1;
    if(pos<=mid) update(lc[id],l,mid,pos);
    if(pos>mid) update(rc[id],mid+1,r,pos);
    push_up(id);
}
int merge(int x,int y,int l,int r){
    if(!x) return y;
    if(!y) return x;
    if(l==r){
        sum[x] += sum[y];
        return x;
    }
    int mid = (l+r)>>1;
    lc[x] = merge(lc[x],lc[y],l,mid);
    rc[x] = merge(rc[x],rc[y],mid+1,r);
    push_up(x);
    return x;
}
int ans[maxn];
int query(int id,int l,int r,int x,int y){
    // printf("query:id = %d l = %d r = %d x =%d y = %d
", id,l,r,x,y);
    if(!id) return 0;
    if(x<=l&&y>=r) return sum[id];
    int mid = (l+r)>>1,ans = 0;
    if(x<=mid) ans += query(lc[id],l,mid,x,y);
    if(y>mid) ans += query(rc[id],mid+1,r,x,y);
    return ans;
}

void debug(int id,int l,int r){
    if(!id) return ;
    printf("id = %d l = %d r = %d sum=%d
", id,l,r,sum[id]);
    if(l==r) return;
    int mid = (l+r)>>1;
    debug(lc[id],l,mid);
    debug(rc[id],mid+1,r);
}

int main(){
    int n = read(),m = read(),q = read();
    now = n,cnt = 0,tot = 0,sz = 0;
    for(int i=1;i<=n+m;i++) f[i] = i;
    for(int i=1;i<=m;i++){
        a[i] = read() + 1,b[i] = read() + 1,c[i] = read();
    }
    for(int i=1;i<=q;i++){
        int x = read() + 1,t = read();
        e[i] = node(x,t,i);
    }
    int cur = m;
    sort(e+1,e+1+q,cmp);
    for(int i=q;i>=1;i--){
        while(cur>=1&&cur>=e[i].t){
            if(c[cur]) unite(a[cur],b[cur]);
            cur--;
        }
        subTree[i] = find(e[i].x);
    }
    for(int i=1;i<=n+m;i++){
        find(i);
        if(f[i]==i) dfs(i,0);
    }
    for(int i=1;i<=n;i++) update(root[i],1,now,el[i]);
    cur = 1;
    for(int i=1;i<=n;i++) f[i] = i;
    for(int i=1;i<=q;i++){
        while(cur<=m&&cur<=e[i].t){
            if(!c[cur]) {
                int x = find(a[cur]),y = find(b[cur]);
                if(x!=y){ 
                    root[x]=root[y]=merge(root[x],root[y],1,now);
                    f[x] = y;
                }
            }
            cur++;
        }
        int pos = root[find(e[i].x)];
        ans[e[i].id] = query(pos,1,now,el[subTree[i]],er[subTree[i]]);
    }
    for(register int i=1;i<=q;++i) write(ans[i]),puts("");
    return 0;
}


原文地址:https://www.cnblogs.com/EchoZQN/p/13818496.html