Solution [LNOI2014]LCA
题目大意:给定一棵树,每次给定 (l,r,z),询问 (sum_{i=l}^{r}dep[LCA(i,z)])
树链剖分
分析:
关键性质在于,从根到两个点的路径的交,等于从根到它们的 (LCA) 的路径。而一个点的深度,就相当于根到那个点的路径长度。
因此原问题等价于每次对于 (x in [l,r]),将根到 (x) 的路径加 (1),然后询问根到 (z) 的路径上的权值之和。
这个可以离线下来,变成将 (x in [1,k]) 的路径加 (1),做个差分就可以了。
直接树剖加上线段树维护。
#include <cstdio>
#include <cctype>
#include <vector>
#pragma GCC optmize(2)
using namespace std;
typedef long long ll;
constexpr int maxn = 5e4 + 100,inf = 0x7fffffff,mod = 201314;
inline int add(const int a,const int b){return (a + b) % mod;}
inline int sub(const int a,const int b){return (a - b + mod) % mod;}
inline int mul(const int a,const int b){return (1ll * a * b) % mod;}
struct IO{//-std=c++11,with cstdio and cctype
private:
static constexpr int ibufsiz = 1 << 20;
char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf;
static constexpr int obufsiz = 1 << 20;
char obuf[obufsiz + 1],*onow = obuf;
const char *oed = obuf + obufsiz;
public:
inline char getchar(){
#ifndef ONLINE_JUDGE
return ::getchar();
#else
if(inow == ied){
ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin);
*ied = ' ';
inow = ibuf;
}
return *inow++;
#endif
}
template<typename T>
inline void read(T &x){
static bool flg;flg = 0;
x = 0;char c = getchar();
while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar();
while(isdigit(c))x = x * 10 + c - '0',c = getchar();
if(flg)x = -x;
}
template <typename T,typename ...Y>
inline void read(T &x,Y&... X){read(x);read(X...);}
inline int readi(){static int res;read(res);return res;}
inline long long readll(){static long long res;read(res);return res;}
inline void flush(){
fwrite(obuf,sizeof(char),onow - obuf,stdout);
fflush(stdout);
onow = obuf;
}
inline void putchar(char c){
#ifndef ONLINE_JUDGE
::putchar(c);
#else
*onow++ = c;
if(onow == oed){
fwrite(obuf,sizeof(char),obufsiz,stdout);
onow = obuf;
}
#endif
}
template <typename T>
inline void write(T x,char split = ' '){
static unsigned char buf[64];
if(x < 0)putchar('-'),x = -x;
int p = 0;
do{
buf[++p] = x % 10;
x /= 10;
}while(x);
for(int i = p;i >= 1;i--)putchar(buf[i] + '0');
if(split != ' ')putchar(split);
}
inline void lf(){putchar('
');}
~IO(){
fwrite(obuf,sizeof(char),onow - obuf,stdout);
}
}io;
template <typename A,typename B>
inline void chkmin(A &x,const B &y){if(y < x)x = y;}
template <typename A,typename B>
inline void chkmax(A &x,const B &y){if(y > x)x = y;}
int n,q,ans[maxn];
namespace st{
#define ls (rt << 1)
#define rs (rt << 1 | 1)
struct node{
int sum,add;
}tr[maxn << 2];
inline int calc(const int l,const int r){return r - l + 1;}
inline void pushup(const int rt){tr[rt].sum = add(tr[ls].sum,tr[rs].sum);}
inline void pushdown(const int rt,const int l,const int r){
tr[ls].add = add(tr[ls].add,tr[rt].add);
tr[rs].add = add(tr[rs].add,tr[rt].add);
int mid = (l + r) >> 1;
tr[ls].sum = add(tr[ls].sum,mul(calc(l,mid),tr[rt].add));
tr[rs].sum = add(tr[rs].sum,mul(calc(mid + 1,r),tr[rt].add));
tr[rt].add = 0;
}
inline void modify(const int a,const int b,const int v,const int l = 1,const int r = n,const int rt = 1){
if(a <= l && b >= r){
tr[rt].add = add(tr[rt].add,v);
tr[rt].sum = add(tr[rt].sum,mul(calc(l,r),v));
return;
}
pushdown(rt,l,r);
const int mid = (l + r) >> 1;
if(a <= mid)modify(a,b,v,l,mid,ls);
if(b >= mid + 1)modify(a,b,v,mid + 1,r,rs);
pushup(rt);
}
inline int query(const int a,const int b,const int l = 1,const int r = n,const int rt = 1){
if(a <= l && b >= r)return tr[rt].sum;
pushdown(rt,l,r);
int mid = (l + r) >> 1,res = 0;
if(a <= mid)res += query(a,b,l,mid,ls);
if(b >= mid + 1)res += query(a,b,mid + 1,r,rs);
return res % mod;
}
#undef ls
#undef rs
}
namespace tree{
vector<int> G[maxn];
inline void addedge(int u,int v){
// io.write(u,' '),io.write(v,'
');
G[u].push_back(v);}
int dfs_tot,dfn[maxn],rnk[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn],faz[maxn];
inline void dfs1(const int u){
siz[u] = 1;
for(int v : G[u]){
dep[v] = dep[u] + 1;
dfs1(v);
siz[u] += siz[v];
if(siz[v] > siz[son[u]])son[u] = v;
}
}
inline void dfs2(const int u,const int tp){
dfn[u] = ++dfs_tot;
rnk[dfs_tot] = u;
top[u] = tp;
if(son[u])dfs2(son[u],tp);
for(int v : G[u]){
if(v == son[u])continue;
dfs2(v,v);
}
}
inline void modify(int u,const int v){
while(u){
st::modify(dfn[top[u]],dfn[u],v);
u = faz[top[u]];
}
}
inline int query(int u){
int res = 0;
while(u){
res = add(res,st::query(dfn[top[u]],dfn[u]));
u = faz[top[u]];
}
return res;
}
}
struct oper{
int id,z,flg;
};
vector<oper> vec[maxn];
int main(){
#ifndef ONLINE_JUDGE
freopen("fafa.in","r",stdin);
#endif
tree::dep[1] = 1;
io.read(n,q);
for(int i = 2;i <= n;i++)
tree::faz[i] = io.readi() + 1,tree::addedge(tree::faz[i],i);
tree::dfs1(1);
tree::dfs2(1,1);
for(int l,r,z,i = 1;i <= q;i++){
io.read(l,r,z);l++,r++,z++;
vec[l - 1].push_back(oper{i,z,-1});
vec[r].push_back(oper{i,z,1});
}
for(int i = 1;i <= n;i++){
tree::modify(i,1);
for(auto it : vec[i])
if(it.flg == 1)ans[it.id] = add(ans[it.id],tree::query(it.z));
else ans[it.id] = sub(ans[it.id],tree::query(it.z));
}
for(int i = 1;i <= q;i++)io.write(ans[i],'
');
return 0;
}