【SHOI2014/Luogu4332】三叉神经树 树链剖分

原题走这里

首先我们定义节点的状态0,1,2,3分别代表该节点分别接收到0,1,2,3个信号。
那么我们会发现,叶子节点的状态改变,会导致叶子节点到根的路径上一连串节点的状态改变。
比如当某叶子节点到根的路径上,
由叶子节点开始的若干个连续的节点均处于状态2,且该叶子节点处于激活状态,
那么此时,如果我们改变这一叶子节点的状态,
则从叶子节点开始,一路向根走,遇到的这些连续的2节点全部会变成状态1,
此外还要对应更新最后一个2节点的父节点。

因此,我们实质上就是要实现以下操作(单点修改之类的就不算了):
1.查询从根到某叶节点有多少个从叶节点开始的连续的1节点或2节点
2.把这些节点变成状态1或2

恩,于是我们可以树链剖分,用线段树维护本区间最右节点的状态,以及从本区间右端点开始有多少个连续的状态1或状态2节点即可。

具体细节见代码如下:
为什么我的代码这么慢啊

#include <bits/stdc++.h>
using namespace std;
char buf[25000000],*pp=buf;
#define getchar() *(pp++)
inline int read() {
    int X=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')w=(ch=='-'?-1:1),ch=getchar();
    while(ch>='0'&&ch<='9')X=X*10+ch-'0',ch=getchar();
    return X*w;
}
struct edge {
    int v,p;
    inline edge(int _v=0,int _p=0) {
        v=_v;
        p=_p;
    }
} e[3000010];
int n,q,head[1500010],top,sr[6000010],siz[1500010],dep[1500010],w[1500010],tp[1500010],f[1500010],son[1500010],m,s[1500010],st[6000010],lazy[6000010];
inline void addedge(int u,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值