2009 Niuke Summer Multi-School Training Camp (Game 8) E Explorer - Search Segment Tree, LCT

Posted by timelf123 on Sat, 05 Oct 2019 05:05:25 +0200

This way

Title:

Give you a picture, each side has an array range that you can pass through. Ask how many numbers you have that can go from 1 to n.

Solution;

There are two main ways to do this: line segment tree and LCT, but I didn't do one when I was playing.
Line segment tree is the same method of building tree as the problem of median in the previous two days, that is, replacing R with r+1, so that b[r+1]-b[l] replaces b[r]-b[l]+1, which saves possible errors. Although there is no push_down here. Then we use vector to record the edges owned by each interval, so that when we query the edges owned by this interval, we can use and collect them to see if 1 and n are connected.
LCT hasn't been filled yet. I'll discuss it later.

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
struct node
{
    int x,y,l,r;
}e[N];
int b[N*2];
vector<int>vec[N*5];
void update(int l,int r,int root,int ql,int qr,int x)
{
    if(l>=ql&&r<=qr)
    {
        vec[root].push_back(x);
        return ;
    }
    int mid=l+r>>1;
    if(mid>=ql)
        update(l,mid,root<<1,ql,qr,x);
    if(mid<qr)
        update(mid+1,r,root<<1|1,ql,qr,x);
}
int fa[N];
int finds(int x){return x==fa[x]?fa[x]:finds(fa[x]);}
int ans,n,m,siz[N];
void query(int l,int r,int root)
{
    vector<int>v;
    for(int i=0;i<vec[root].size();i++)
    {
        int x=vec[root][i];
        int fax=finds(e[x].x),fay=finds(e[x].y);
        if(fax!=fay)
        {
            if(siz[fax]<siz[fay])
                swap(fax,fay);
            fa[fay]=fax;
            v.push_back(fay);
            siz[fax]+=siz[fay];
        }
    }
    if(finds(1)==finds(n))
        ans+=b[r+1]-b[l];
    else if(l<r)
    {
        int mid=l+r>>1;
        query(l,mid,root<<1);
        query(mid+1,r,root<<1|1);
    }
    for(int i=0;i<v.size();i++)
        fa[v[i]]=v[i];
    v.clear();
}
int main()
{

    for(int i=1;i<N;i++)
        fa[i]=i,siz[i]=1;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].l,&e[i].r),b[i*2-1]=e[i].l,b[i*2]=e[i].r+1;
    sort(b+1,b+1+m*2);
    int all=unique(b+1,b+1+m*2)-b-1;
    for(int i=1;i<=m;i++)
        update(1,all,1,lower_bound(b+1,b+1+all,e[i].l)-b,lower_bound(b+1,b+1+all,e[i].r+1)-b-1,i);
    query(1,all,1);
    printf("%d\n",ans);
    return 0;
}