• CF763E Timofey and our friends animals


    Description

    After his birthday party, Timofey went to his favorite tree alley in a park. He wants to feed there his favorite birds — crows.

    It's widely known that each tree is occupied by a single crow family. The trees in the alley form a row and are numbered from $1$ to $n$ . Some families are friends to each other. For some reasons, two families can be friends only if they live not too far from each other, more precisely, there is no more than $k-1$ trees between any pair of friend families. Formally, the family on the $u$ -th tree and the family on the $v$ -th tree can be friends only if $|u-v| leq k$ holds.

    One of the friendship features is that if some family learns that Timofey is feeding crows somewhere, it notifies about this all friend families. Thus, after Timofey starts to feed crows under some tree, all the families that are friends to the family living on this tree, as well as their friends and so on, fly to the feeding place. Of course, the family living on the tree also comes to the feeding place.

    Today Timofey came to the alley and noticed that all the families that live on trees with numbers strictly less than $l$ or strictly greater than $r$ have flown away. Thus, it is not possible to pass the information about feeding through them. Moreover, there is no need to feed them. Help Timofey to learn what is the minimum number of trees under which he has to feed crows so that all the families that have remained will get the information about feeding. You are given several situations, described by integers $l$ and $r$ , you need to calculate the answer for all of them.

    Solution

    要求区间的连通块个数,答案为区间长度减去区间中边的数量(排除一个环中左端点最小的的边,其不产生贡献)

    询问离线,按照右端点排序,每条边的权值设为左端点编号,维护最大生成树

    可以用LCT,统计答案时使用树状数组

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,K,m,pos=1,q,val[600005],ans[100005];
    const int inf=0x7f7f7f7f;
    struct Edge{
        int u,v;
        bool operator <(const Edge &z)const{return v<z.v;}
    }edge[500005];
    struct Q{
        int l,r,id;
        bool operator <(const Q &z)const{return r<z.r;}
    }que[100005];
    inline int read(){
        int f=1,w=0;
        char tr=0;
        while(tr<'0'||tr>'9'){if(tr=='-') f=-1;tr=getchar();}
        while(tr>='0'&&tr<='9') w=(w<<1)+(w<<3)+tr-'0',tr=getchar();
        return f*w;
    }
    namespace SGT{
        int a[100005];
        void add(int x,int v){while(x<=n)a[x]+=v,x+=x&-x;}
        int query(int x){
            int ret=0;
            while(x)ret+=a[x],x-=x&-x;
            return ret;
        }
    }
    namespace LCT{
        int fa[600005],tr[600005][2],minn[600005],st[600005],tag[600005];
        bool nroot(int x){return tr[fa[x]][0]==x||tr[fa[x]][1]==x;}
        int getson(int x){return tr[fa[x]][1]==x;}
        void pushup(int x){
            minn[x]=x;
            if(val[minn[tr[x][0]]]<val[minn[x]])minn[x]=minn[tr[x][0]];
            if(val[minn[tr[x][1]]]<val[minn[x]])minn[x]=minn[tr[x][1]];
        }
        void pushdown(int x){
            if(tag[x]){
                swap(tr[x][0],tr[x][1]);
                if(tr[x][0])tag[tr[x][0]]^=1;
                if(tr[x][1])tag[tr[x][1]]^=1;
                tag[x]=0;
            }
        }
        void rotate(int x){
            int y=fa[x],z=fa[y],b=getson(x),c=getson(y),a=tr[x][!b];
            if(nroot(y))tr[z][c]=x;
            fa[x]=z,tr[x][!b]=y,fa[y]=x,tr[y][b]=a;
            if(a)fa[a]=y;
            pushup(y),pushup(x);
        }
        void splay(int x){
            int top=0;
            st[++top]=x;
            for(int i=x;nroot(i);i=fa[i])st[++top]=fa[i];
            while(top)pushdown(st[top--]);
            while(nroot(x)){
                int y=fa[x];
                if(nroot(y))if(getson(x)==getson(y))rotate(y);
                else rotate(x);
                rotate(x);
            }
        }
        void access(int x){for(int y=0;x;x=fa[y=x])splay(x),tr[x][1]=y,pushup(x);}
        int findroot(int x){
            access(x),splay(x);
            while(tr[x][0])x=tr[x][0];
            return x;
        }
        void makeroot(int x){access(x),splay(x),tag[x]^=1;}
        void split(int x,int y){makeroot(x),access(y),splay(y);}
        void link(int x,int y){split(x,y),fa[x]=y,pushup(y);}
        void cut(int x,int y){split(x,y),fa[x]=tr[y][0]=0;}
        void insert(int x){
            int u=edge[x].u,v=edge[x].v;
            if(findroot(u)!=findroot(v)){link(u,n+x),link(n+x,v),SGT::add(n-u+1,1);return;}
            split(u,v);
            int w=minn[v];
            if(val[w]>=val[x+n])return;
            cut(w,edge[w-n].u),cut(w,edge[w-n].v),SGT::add(n-val[w]+1,-1),link(u,n+x),link(n+x,v),SGT::add(n-u+1,1);
        }
    }
    int main(){
        n=read(),K=read(),m=read(),memset(val,127,sizeof(val));
        for(int i=1;i<=m;i++){
            edge[i]=(Edge){read(),read()};
            if(edge[i].u>edge[i].v)swap(edge[i].u,edge[i].v);
        }
        sort(edge+1,edge+m+1),q=read();
        for(int i=1;i<=m;i++)val[i+n]=edge[i].u;
        for(int i=1;i<=q;i++)que[i]=(Q){read(),read(),i};
        sort(que+1,que+q+1);
        for(int i=1;i<=q;i++){
            while(edge[pos].v<=que[i].r&&pos<=m)LCT::insert(pos),++pos;
            ans[que[i].id]=que[i].r-que[i].l+1-SGT::query(n-que[i].l+1);
        }
        for(int i=1;i<=q;i++)printf("%d
    ",ans[i]);
        return 0;
    }
    Timofey and our friends animals
  • 相关阅读:
    Gym
    struts2.5 使用感叹号和通配符实现动态方法调用无效的问题及解决!
    Offfice 多重版本key残留并存的异常问题
    IDEA Struts2 truts-default显红的解决办法
    Struts2的库在 IDEA 的外联库就会报错,不知道为什么。
    计算机二级python 知识点篇(第三方库)
    计算机二级python 知识点篇(python标准库)
    计算机二级python 知识点篇(内置函数整理)
    计算机二级python 知识点篇(文件和数据格式化)
    计算机二级python 知识点篇(组合数据类型)
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14321345.html
Copyright © 2020-2023  润新知