Codeforces 165D Beard Graph 边权树剖+树状数组

Beard Graph

题意:给你一颗由n个结点组成的树,支持以下操作:1 i:将第i条边染成黑色(保证此时该边是白色),2 i:将第i条边染成白色(保证此时该边是黑色),3 a b:找出a,b两点之间只由黑边组成的最短路径.

思路:树链剖分+树状数组,把每条边的权值放到它指向的点中去,初始全为黑边,黑边权值为1,白边权值为-inf,黑边变白边,将点权增加-inf,白边变黑边点权增加inf,因为不可能白边变白边,所以可以这样做,查询的时候要减去2个点的最近公共祖先的点权,最近公共祖先可通过树剖的get函数求,查询结果<0说明不可能到达

AC代码:

#include "iostream"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#define ll long long
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
using namespace std;
const long long INF = 1e18+1LL;
const int inf = 1e9+1e8;
const int N=1e5+100;
const ll mod=1e9+7;

int to[N<<1],nex[N<<1],head[N],tot=2;
int siz[N],son[N],tip[N],top[N],dep[N],fa[N],cnt=0;
int n,m;
ll C[N];
map<int,int> M;
void add(int u, int v){
    to[tot]=v;
    nex[tot]=head[u];
    head[u]=tot++;
}
void dfs1(int u, int f){
    siz[u]=1;
    fa[u]=f;
    dep[u]=dep[f]+1;
    for(int i=head[u]; i!=-1; i=nex[i]){
        int v=to[i];
        if(v==f) continue;
        M[i>>1]=v;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]]) son[u]=v;
    }
}
void dfs2(int u, int tp){
    tip[u]=++cnt;
    top[u]=tp;
    if(son[u]) dfs2(son[u],tp);
    for(int i=head[u]; i!=-1; i=nex[i]){
        int v=to[i];
        if(v!=fa[u] && v!=son[u]) dfs2(v,v);
    }
}
int lowbit(int x){
    return (-x)&x;
}
void up(int x, ll c){
    while(x<=n){
        C[x]+=c;
        x+=lowbit(x);
    }
}
ll sum(int l, int r){
    ll ret=0;
    l--;
    while(l>0){
        ret-=C[l];
        l-=lowbit(l);
    }
    while(r>0){
        ret+=C[r];
        r-=lowbit(r);
    }
    return ret;
}
void get_sum(int u, int v){
    ll ans=0;
    while(top[u]!=top[v]){
        if(dep[top[u]] < dep[top[v]]) swap(u,v);
        ans+=sum(tip[top[u]], tip[u]);
        u=fa[top[u]];
    }
    if(dep[u] > dep[v]) swap(u,v); //u为LCA
    ans+=sum(tip[u],tip[v]);
    ans-=sum(tip[u],tip[u]);
    if(ans<0) cout<<"-1\n";
    else cout<<ans<<"\n";
}
int main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n;
    mem(head,-1);
    int c,u,v;
    for(int i=1; i<n; ++i){
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    dfs1(1,1);
    dfs2(1,1);
    for(int i=2; i<=n; ++i){
        up(i,1);
    }
    cin>>m;
    while(m--){
        cin>>c>>u;
        if(c==3){
            cin>>v;
            get_sum(u,v);
        }
        else if(c==2) up(tip[M[u]],-inf);
        else{
            //ll t=sum(1,tip[M[u]])-sum(1,tip[M[u]]-1);
            up(tip[M[u]],inf);
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/max88888888/p/7253014.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值