首页 > 其他 > 详细

CF165D Beard Graph

时间:2019-10-26 10:33:39      阅读:125      评论:0      收藏:0      [点我收藏+]

这就是一个树剖裸题,但给的是边权。

这题会板子的话,只需考虑如何来写线段树维护这道题维护的东西和边权化点权。

我对于边权化点权是在两点连线之间建立一个点,把边

权给它,节点数就会变为 2*n+1 ,而代表边的点编号都为边的编号加n。

每次修改的时候把x改成x+n就是要修改边所对应的的编号。

对于黑边,给它赋值为1,而白边赋值为0,修改就是单点修改,查询的话,查询区

间和,再利用树剖LCA判断两点之间的距离是否是ans的2倍,若是,则全是黑边,

若不是则输出-1。然后这题就做完了。

AC代码

#include<iostream>
#include<cstdio>
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
#define ls k<<1
#define rs k<<1|1
#define mid ((l+r)>>1)
using namespace std;
const int N=200005;
int n,m,cnt,tot,ans;
int head[N],id[N],top[N],fa[N],siz[N],son[N],dep[N],dfn[N];
int tr[N<<2];
bool flag;
struct node{
    int to,nxt;
}e[N<<1];
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<0||ch>9){if(ch==-)w=-1;ch=getchar();}
    while(ch>=0&&ch<=9){s=s*10+ch-0;ch=getchar();}
    return s*w;
}
inline void add(int from,int to){
    e[++cnt]=(node){to,head[from]};
    head[from]=cnt;
}
void dfs1(int x,int f){
    dep[x]=dep[f]+1;fa[x]=f;siz[x]=1;
    int y;
    for(int i=head[x];i;i=e[i].nxt){
        y=e[i].to;
        if(y==f)continue;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(siz[y]>siz[son[x]])son[x]=y;
    }
}
void dfs2(int x,int topf){
    top[x]=topf;id[x]=++tot;dfn[tot]=x;
    if(!son[x])return ;
    dfs2(son[x],topf);
    int y;
    for(int i=head[x];i;i=e[i].nxt){
        y=e[i].to;
        if(y==fa[x]||y==son[x])continue;
        dfs2(y,y);
    }
}
inline void update(int k){
    tr[k]=tr[ls]+tr[rs];
}
void build(int k,int l,int r){
    if(l==r){
        tr[k]=dfn[l]>n?1:0;
        return ;
    }
    build(lson);build(rson);
    update(k);
}
void change(int k,int l,int r,int x,int y){
    if(l==r&&x==l){
        tr[k]=y;
        return ;
    }
    if(x<=mid)change(lson,x,y);
    else change(rson,x,y);
    update(k);
}
int ask(int k,int l,int r,int x,int y){
    if(l==x&&y==r){
        return tr[k];
    }
    if(y<=mid)return ask(lson,x,y);
    else if(x>mid)return ask(rson,x,y);
    else return ask(lson,x,mid)+ask(rson,mid+1,y);
}
inline void qurey(int x,int y){
    ans=0;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        ans+=ask(1,1,n*2-1,id[top[x]],id[x]);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    ans+=ask(1,1,n*2-1,id[x],id[y]);
}
inline int LCA(int x, int y) {
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        x=fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}
inline void check(int x,int y){
    int dis=dep[x]+dep[y]-2*dep[LCA(x,y)];
    if(dis!=ans*2)flag=1;
}
int main(){
    n=read();
    int x,y;
    for(int i=1;i<n;++i){
        x=read();y=read();
        add(x,i+n);add(i+n,x);
        add(i+n,y);add(y,i+n);
    }
    dfs1(1,0);
    dfs2(1,1);
    build(1,1,n*2-1);
    m=read();
    int opt;
    while(m--){
        opt=read();x=read();
        if(opt==1)change(1,1,n*2-1,id[x+n],1);
        else if(opt==2)change(1,1,n*2-1,id[x+n],0);
        else {
            flag=0;
            y=read();
            qurey(x,y);
            check(x,y);
            if(flag)printf("-1\n");
            else printf("%d\n",ans);
        }
    }
}

 

CF165D Beard Graph

原文:https://www.cnblogs.com/sanjinliushi/p/11741703.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!