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

题目思路挺巧妙的。

感觉应该可以数据结构一波,发现n很小可以搞搞事啊。然后又发现给了512mb,顿时萌生大力线段树记录的念头

一开始想的是记录节点的fa,然后发现搞不动啊??

但其实边肯定最多只有n-1条,那么就可以记录选择的边,然后用归并合并即可

没清空答案还wa可一次(lll¬ω¬),浪费时间写暴力和拍(lll¬ω¬)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int m; 
struct edge
{
    int x,y,d;
}e[110000];

struct node
{
    int l,r,lc,rc,as[110];
}tr[210000];int trlen;

int n,fa[110];
int findfa(int x)
{
    if(fa[x]==x)return x;
    fa[x]=findfa(fa[x]);return fa[x];
}
void mergesort(int now,int lc,int rc)
{
    for(int i=1;i<=n;i++)fa[i]=i;
    
    int Llim=min(n-1,tr[lc].r-tr[lc].l+1);
    int Rlim=min(n-1,tr[rc].r-tr[rc].l+1);
    
    int p=1,i=1,j=1;    int fx,fy;
    while(i<=Llim&&j<=Rlim&&p<=n-1)
    {
        int Lid=tr[lc].as[i],Rid=tr[rc].as[j];
        if(e[Lid].d<e[Rid].d)
        {
            fx=findfa(e[Lid].x);fy=findfa(e[Lid].y);
            if(fx!=fy)
            {
                fa[fx]=fy;
                tr[now].as[p++]=Lid;
            }
            i++;
        }
        else
        {
            fx=findfa(e[Rid].x);fy=findfa(e[Rid].y);
            if(fx!=fy)
            {
                fa[fx]=fy;
                tr[now].as[p++]=Rid;
            }
            j++;
        }
    }
    while(i<=Llim&&p<=n-1)
    {
        int id=tr[lc].as[i];
        fx=findfa(e[id].x),fy=findfa(e[id].y);
        if(fx!=fy)
        {
            fa[fx]=fy;
            tr[now].as[p++]=id;
        }
        i++;
    }
    while(j<=Rlim&&p<=n-1)
    {
        int id=tr[rc].as[j];
        fx=findfa(e[id].x),fy=findfa(e[id].y);
        if(fx!=fy)
        {
            fa[fx]=fy;
            tr[now].as[p++]=id;
        }
        j++;
    }
}

//-----------merge-----------------------------

void bt(int l,int r)
{
    int now=++trlen;
    tr[now].l=l;tr[now].r=r;
    tr[now].lc=tr[now].rc=-1;
    if(l==r)tr[now].as[1]=l;
    else
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
        mergesort(now,tr[now].lc,tr[now].rc);
    }
}
void query(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r)
    {
        tr[trlen+2]=tr[trlen+1]; 
        mergesort(trlen+1,trlen+2,now);
        tr[trlen+1].r=tr[now].r;
        return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    
         if(r<=mid)  query(lc,l,r);
    else if(mid+1<=l)query(rc,l,r);
    else query(lc,l,mid), query(rc,mid+1,r);
}
int main()
{
    freopen("data.in","r",stdin);
    freopen("1.out","w",stdout);
    
    int Q;
    scanf("%d%d%d",&n,&m,&Q);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].d);
    trlen=0;bt(1,m);
    
    int l,r;
    while(Q--)
    {
        scanf("%d%d",&l,&r);
        tr[trlen+1].l=l;tr[trlen+1].r=l-1;
        memset(tr[trlen+1].as,0,sizeof(tr[trlen+1].as));
        query(1,l,r);
        
        long long ans=0;
        for(int i=1;i<=min(n-1,r-l+1);i++)
            ans+=((long long)(e[tr[trlen+1].as[i]].d));
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/8990208.html