• 2019牛客暑期多校训练营(第八场)E:Explorer(LCT裸题 也可用线段树模拟并查集维护连通性)


    题意:给定N,M,然后给出M组信息(u,v,l,r),表示u到v有[l,r]范围的通行证有效。问有多少种通行证可以使得1和N连通。

    思路:和bzoj魔法森林有点像,LCT维护最小生成树。  开始和队友在想维护连通性,而不是维护树,这样好像会很麻烦。

    队友yy了一个算法:用线段树模拟并查集维护连通性。(发现和标程有点像?

    我的代码:LCT维护最小生成树。

    ...先给代码,后面补一下题解。

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    vector<int>e[800010];
    int n,m,t[800010],q[800010],siz[100010],ans,efree,a[200010],cnt,l[100010],r[100010],u[100010],v[100010],f[100010];
    template<class T>
    inline void read(T&a){
        char c=getchar();
        for(a=0;(c<'0'||c>'9')&&c!='-';c=getchar());
        bool f=0;if(c=='-')f=1,c=getchar();
        for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
        if(f)a=-a;
    }
    inline int gf(int x){return x==f[x]?f[x]:gf(f[x]);}
    void ins(int k,int nl,int nr,int l,int r,int x){
        if(nl==l&&nr==r)return (void)e[k].push_back(x);
        int mid=(nl+nr)>>1;
        if(r<=mid)ins(k<<1,nl,mid,l,r,x);
        else if(l>mid)ins(k<<1|1,mid+1,nr,l,r,x);
        else ins(k<<1,nl,mid,l,mid,x),ins(k<<1|1,mid+1,nr,mid+1,r,x);
    }
    void dfs(int k,int l,int r){
        vector<int>lastf;
        int m=e[k].size(),mid=(l+r)>>1;
        for(register int i=0;i<m;i++){
            int x=u[e[k][i]],y=v[e[k][i]];
            x=gf(x),y=gf(y);
            if(siz[x]>siz[y])swap(x,y);
            lastf.push_back(x);f[x]=y;siz[y]+=siz[x];
        }
        if(gf(1)==gf(n))ans+=a[r+1]-a[l];
        else if(l<r)dfs(k<<1,l,mid),dfs(k<<1|1,mid+1,r);
        m=lastf.size();
        for(register int i=m-1;i>=0;i--)f[lastf[i]]=lastf[i];
        lastf.clear();
    }
    int main(){
        read(n),read(m);
        for(int i=1;i<=n;i++)f[i]=i,siz[i]=1;
        for(int i=1;i<=m;i++){
            read(u[i]),read(v[i]),read(l[i]),read(r[i]);
            a[++cnt]=l[i];a[++cnt]=r[i]+1;
        }
        sort(a+1,a+1+cnt);cnt=unique(a+1,a+1+cnt)-a-1;
        for(int i=1;i<=m;i++)
            ins(1,1,cnt-1,lower_bound(a+1,a+1+cnt,l[i])-a,lower_bound(a+1,a+1+cnt,r[i]+1)-a-1,i);
        dfs(1,1,cnt-1);printf("%d
    ",ans);
        return 0;
    }

    LCT代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=400010;
    const int inf=1000000000;
    struct edge{
        int x,y,a,b;
    }e[maxn];
    bool cmp (edge w,edge v){
        return w.b>v.b;
    }
    void read(int &x){
        char c=getchar(); x=0;
        for(;c>'9'||c<'0';c=getchar());
        for(;c<='9'&&c>='0';c=getchar()) x=(x<<3)+(x<<1)+c-'0';
    }
    struct LCT
    {
        int Max[maxn],rev[maxn],ch[maxn][2],fa[maxn],stc[maxn],top;
        int isroot(int x){
            return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
        }
        int get(int x){
            return ch[fa[x]][1]==x;
        }
        void pushdown(int x)
        {
            if(!rev[x]||!x) return ;
            swap(ch[x][0],ch[x][1]);
            if(ch[x][0]) rev[ch[x][0]]^=1;
            if(ch[x][1]) rev[ch[x][1]]^=1;
            rev[x]=0;
        }
        void pushup(int x)
        {
            Max[x]=x;
            if(ch[x][0]&&e[Max[ch[x][0]]].a>e[Max[x]].a) Max[x]=Max[ch[x][0]];
            if(ch[x][1]&&e[Max[ch[x][1]]].a>e[Max[x]].a) Max[x]=Max[ch[x][1]];
        }
        void rotate(int x)
        {
            int old=fa[x],fold=fa[old],opt=get(x);
            if(!isroot(old)) ch[fold][get(old)]=x;
            fa[x]=fold;
            ch[old][opt]=ch[x][opt^1]; fa[ch[old][opt]]=old;
            ch[x][opt^1]=old; fa[old]=x;
            pushup(old); pushup(x);
        }
        void splay(int x)
        {
            int top=0; stc[++top]=x;
            for(int i=x;!isroot(i);i=fa[i]) stc[++top]=fa[i];
            for(int i=top;i;i--) pushdown(stc[i]);
            for(int f;!isroot(x);rotate(x)){
                if(!isroot(f=fa[x]))
                  rotate(get(x)==get(f)?f:x);
            }
        }
        void access(int x)
        {
            int rson=0;
            for(;x;rson=x,x=fa[x]){
                splay(x);
                ch[x][1]=rson;
                pushup(x);
            }
        }
        int find(int x){ access(x); splay(x); while(ch[x][0]) x=ch[x][0]; return x;}
        int query(int x,int y) { make_root(y); access(x);  splay(x); return Max[x]; }
        void make_root(int x) { access(x); splay(x); rev[x]^=1; }
        void link(int x,int y) { make_root(x); fa[x]=y; splay(x); }
        void cut(int x,int y) { make_root(x); access(y); splay(y); fa[x]=ch[y][0]=0; }
    }S;
    pair<int,int>fcy[maxn]; int tot;
    int main()
    {
        int N,M,i,ans=0;
        read(N); read(M);
        for(i=1;i<=M;i++){
            read(e[i].x); read(e[i].y);
            read(e[i].a); read(e[i].b);
        }
        sort(e+1,e+M+1,cmp);
        for(i=1;i<=M;i++){
            if(S.find(M+e[i].x)!=S.find(M+e[i].y)) {
                 S.link(i,M+e[i].x);
                 S.link(i,M+e[i].y);
            }
            else{
                int tmp=S.query(M+e[i].x,M+e[i].y);
                if(e[tmp].a>e[i].a) {
                    S.cut(tmp,M+e[tmp].x); S.cut(tmp,M+e[tmp].y);
                    S.link(i,M+e[i].x); S.link(i,M+e[i].y);
                }
            }
            if(S.find(M+1)==S.find(M+N)){
                int tmp=S.query(M+1,M+N);
                if(e[tmp].a<=e[i].b){
                     tot++;
                     fcy[tot].first=e[tmp].a; fcy[tot].second=e[i].b;
                }
            }
        }
        sort(fcy+1,fcy+tot+1);
        for(i=1;i<=tot;i++){
            int j=i,Mx=fcy[i].second;
            while(j+1<=tot&&fcy[j+1].first<=Mx) {
                j++; Mx=max(Mx,fcy[j].second);
            }
            ans+=Mx-fcy[i].first+1;
            i=j;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Warsaw University Contest Petrozavodsk, Thursday, January 31, 2008 J题,Gym100096J
    FZU2282--错排公式
    POJ 3468 区间加减 区间求和
    HDU 1556 树状数组
    HDU 5480 树状数组
    Tomcat
    Nginx
    Centos7安装后无法联网
    限制服务器ssh登录及防御措施
    DHCP
  • 原文地址:https://www.cnblogs.com/hua-dong/p/11332115.html
Copyright © 2020-2023  润新知