【省选组】模拟gmoj3978. 寝室管理

r 64 有一个好朋友,叫r 128 。r 128 是寄宿生,并且最近被老师叫过去当宿管了。宿
管可不是一件很好做的工作,碰巧r 128 有一个工作上的问题想请r 64 帮忙解决。
r 128 的寝室条件不是很好,所以没有很多钱来装修。n间寝室仅由n − 1条双向道
路连接,而且任意两间寝室之间都可以互达。最近,r 128 被要求对一条路径上的所有
寝室进行管理, 这条路径不会重复经过某个点或某条边。 但他不记得是哪条路径了。
他只记得这条路径上有不少于k个寝室。于是,他想请r 64 帮忙数一下,有多少条这
样的路径满足条件。
嗯...还有一个问题。由于最近有一些熊孩子不准晚上讲话很不爽,他们决定修筑
一条“情报通道”,如果通道建成,寝室就变成了一个n个点n条边的无向图。并且,
经过“情报通道”的路径也是合法的。r 128 心想:通道建成之前,r 64 还有一个高效
的算法帮我数路径条数,但是通道建成之后,他还有办法吗?对,r 64 手忙脚乱,根
本数不清有多少条路径。于是他找到了你。

 

这道题考场时脑瘫了,50分的暴力打了点分治。

正解也是点分治,对于n=m的情况,可以将环上某一条边去掉,转化成一棵树,用点分治求答案。

然后再单独考虑这个环的情况,可以从断边的一个端点开始扫,统计这个端点顺时针走到断边的答案,再将这个端点逆时针走到端点的答案加入到线段树中。

这里偷一个大佬博客的图。

 

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 300000
#define ll long long
using namespace std;
ll n,m,len,i,j,x,y,q[N],size[N],sizen,root,mxs[N],tot,ans,num,a[N],bz[N],bzp[N],bzx,bzy;
ll stk[N],top,hu[N],cnt,ls[N],bzf[N];
struct edge{
    ll to,next;
}e[N];
struct node{
    ll sum;
}f[N*10];
void insert(ll x,ll y){
    tot++;
    e[tot].to=y;
    e[tot].next=q[x];
    q[x]=tot;
}
void getroot(ll x,ll father){
    ll i,y;
    size[x]=1;
    mxs[x]=0;
    for (i=q[x];i;i=e[i].next){
        y=e[i].to;
        if (x==bzx&&y==bzy||x==bzy&&y==bzx)
            continue;
        if (y!=father&&!bz[y]){
            getroot(y,x);
            size[x]+=size[y];
            mxs[x]=max(mxs[x],size[y]);
        }
    }
    mxs[x]=max(mxs[x],sizen-size[x]);
    if (mxs[x]<mxs[root])
        root=x;
}
void dfs1(ll x,ll ed,ll father,ll opt){
    a[++num]=ed;
    ll i,y;
    for (i=q[x];i;i=e[i].next){
        y=e[i].to;
        if (x==bzx&&y==bzy||x==bzy&&y==bzx)
            continue;
        if (y!=father&&bz[y]==0&&opt==1||y!=father&&opt==0&&bzf[y]==0)
            dfs1(y,ed+1,x,opt);
    }
}
ll getans(ll x,ll ed){
    num=0;
    dfs1(x,ed,0,1);
    ll l=1,r=num,sum=0;
    sort(a+1,a+num+1);
    while (true){
        while (l<=num&&a[l]+a[r]<len)
            l++;
        if (r<l)
            break;
        sum+=r-l;
        if (a[r]>=len)
            sum++;
        r--;
    }
    return sum;
}
void dfs(ll x){
    ans+=getans(x,0);
    ll i,y;
    bz[x]=1;
    for (i=q[x];i;i=e[i].next){
        y=e[i].to;
        if (x==bzx&&y==bzy||x==bzy&&y==bzx)
            continue;
        if (!bz[y]){
            ans-=getans(y,1);
            root=0;
            sizen=size[y];
            getroot(y,0);
            dfs(root);
        }
    }
}
void dfsp(ll x,ll father){
    ll i,y;
    if (bzp[x]){
        bzx=x;
        bzy=father;
        while (stk[top]!=x){
            hu[++cnt]=stk[top];
            ls[cnt]=ls[cnt-1]+1;
            bzf[stk[top]]=1;
            top--;
        }
        hu[++cnt]=stk[top];
        ls[cnt]=ls[cnt-1]+1;
        bzf[stk[top]]=1;
        top--;
        return;
    }
    bzp[x]=1;
    stk[++top]=x;
    for (i=q[x];i;i=e[i].next){
        y=e[i].to;
        if (y!=father)
            dfsp(y,x);
        if (bzx)
            return;
    }
    top--;
}
void change(ll x,ll l,ll r,ll k){
    if (l==r){
        f[x].sum++;
        return;
    }
    ll mid=(l+r)/2;
    if (k<=mid)
        change(x*2,l,mid,k);
    else
        change(x*2+1,mid+1,r,k);
    f[x].sum=f[x*2].sum+f[x*2+1].sum;
}
ll find(ll x,ll l,ll r,ll l1,ll r1){
    if (l1<=l&&r1>=r)
        return f[x].sum;
    ll sum=0,mid=(l+r)/2;
    if (l1<=mid)
        sum+=find(x*2,l,mid,l1,r1);
    if (r1>mid)
        sum+=find(x*2+1,mid+1,r,l1,r1);
    return sum;
}
int main(){
    scanf("%lld%lld%lld",&n,&m,&len);
    len--;
    for (i=1;i<=m;i++){
        scanf("%lld%lld",&x,&y);
        insert(x,y);
        insert(y,x);
    }
    dfsp(1,0);
    mxs[0]=1e9;
    root=0;
    sizen=n;
    getroot(1,0);
    dfs(root);
    if (m==n-1){
        printf("%lld\n",ans);
        return 0;
    }
    num=0;
    dfs1(bzx,0,0,0);
    for (i=1;i<=num;i++)
        change(1,0,n,a[i]);
    for (i=cnt-1;i>=1;i--){
        num=0;
        dfs1(hu[i],0,0,0);
        for (j=1;j<=num;j++)
            ans+=find(1,0,n,len-ls[i]-a[j],n);
        for (j=1;j<=num;j++)
            change(1,0,n,a[j]+ls[cnt]-ls[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2020-09-26 16:12  Mohogany  阅读(147)  评论(0编辑  收藏  举报