[BZOJ4573][ZJOI2016]大♂森林

bzoj
luogu
uoj

sol

\(orz\ \ HJT\ \ dalao\)教会我做这道题。
考虑每两个相邻位置的树的差异。
对于一个1操作(更换生长节点),假设区间是\([l,r]\),那么第\(l-1\)棵树和第\(l\)棵数就会产生一定的差异,具体来说,假设在这之后没有1操作了,那么所有应该在第\(l-1\)棵树中接到原生长节点下面的点都在第\(l\)棵树中被接到了新的生长节点的下面。
我们考虑怎么快速实现这个操作。很显然,我们只要把修改了生长节点后新长出来的点打个包,然后\(cut\)\(link\)一下就好了。
如果是一棵子树,直接对根节点进行操作就行了。
但是显然并不是一棵子树啊。
那就直接新建一个点把新建的点接在下面就好了。
具体来说,对于每一个1操作,新建一个虚点,把所有从这个生长节点长出来的点接在下面。
在处理到第\(l\)棵树时,把这个虚点接到那个生长节点的下面去;处理到第\(r+1\)棵树的时候再把虚点接到前一个生长节点对应的虚点上去。
这样就可以直接查询两个点的路径长度了。
但是有新建的虚点?
直接把实点的权值设为1,虚点的权值设为0,然后查路径和就好了。
但是这是一棵有根树,并不能\(split\)啊。
所以可以查\(s[x]+s[y]-2*s[lca(x,y)]\)
现在的问题是:怎么在\(LCT\)\(LCA\)
\(access(x)\),然后在\(access(y)\)的时候,最后一个由虚边改为实边的位置就是\(LCA\)
这个画个图就能理解了吧。
然后这题就做完了。

code

#include<cstdio>
#include<algorithm>
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 4e5+5;
struct node{
    int pos,tim,x,y;
    bool operator < (const node &b) const
        {return pos!=b.pos?pos<b.pos:tim<b.tim;}
}q[N];
int n,m,cnt,Q,fa[N],ch[2][N],val[N],sum[N],grow,real,tot,id[N],L[N],R[N],ans[N];
bool son(int x){return x==ch[1][fa[x]];}
bool isroot(int x)
{
    return x!=ch[0][fa[x]]&&x!=ch[1][fa[x]];
}
void pushup(int x)
{
    sum[x]=sum[ch[0][x]]+sum[ch[1][x]]+val[x];
}
void rotate(int x)
{
    int y=fa[x],z=fa[y],c=son(x);
    ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
    fa[x]=z;if (!isroot(y)) ch[son(y)][z]=x;
    ch[c^1][x]=y;fa[y]=x;pushup(y);
}
void splay(int x)
{
    for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
        if (!isroot(y)) son(x)^son(y)?rotate(x):rotate(y);
    pushup(x);
}
int access(int x)
{
    int y=0;
    for (;x;y=x,x=fa[x])
        splay(x),ch[1][x]=y,pushup(x);
    return y;
}
void link(int x,int y)
{
    access(x);splay(x);fa[x]=y;
}
void cut(int x)
{
    access(x);splay(x);
    ch[0][x]=fa[ch[0][x]]=0;pushup(x);
}
int main()
{
//  freopen("a.in","r",stdin);
//  freopen("a.out","w",stdout);
    n=gi();m=gi();link(2,1);val[1]=1;id[1]=1;
    L[1]=1;R[1]=n;grow=tot=2;real=1;
    for (int i=1;i<=m;++i)
    {
        int opt=gi(),l=gi(),r=gi();
        if (!opt)
        {
            link(id[++real]=++tot,grow);val[tot]=1;
            L[real]=l;R[real]=r;
        }
        if (opt==1)
        {
            int x=gi();l=max(l,L[x]),r=min(r,R[x]);
            if (l>r) continue;
            link(++tot,grow);
            q[++cnt]=(node){l,i-m,tot,id[x]};q[++cnt]=(node){r+1,i-m,tot,grow};
            grow=tot;
        }
        if (opt==2)
        {
            int x=gi();
            q[++cnt]=(node){l,++Q,id[r],id[x]};
        }
    }
    sort(q+1,q+cnt+1);
    for (int i=1;i<=cnt;++i)
        if (q[i].tim>0)
        {
            int res,gg;
            access(q[i].x);splay(q[i].x);res=sum[q[i].x];
            gg=access(q[i].y);splay(q[i].y);res+=sum[q[i].y];
            access(gg);splay(gg);res-=sum[gg]<<1;
            ans[q[i].tim]=res;
        }
        else cut(q[i].x),link(q[i].x,q[i].y);
    for (int i=1;i<=Q;++i) printf("%d\n",ans[i]);
    return 0;
}

转载于:https://www.cnblogs.com/zhoushuyu/p/8748048.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 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
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、付费专栏及课程。

余额充值