主席树维护树链剖分…
一开始直接套了个贪心的线段树…
发现t的没边了….这就很尴尬呀..
观察后发现可以把一个询问转换为寻求区间有多少小于i-c-1的数.
发现这个性质就很好,一个主席树可以很轻松的解决,那么套上就好啦.
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 2e5 + 500;
int n,root,f[N],w[N],rt[N];
int head[N],nxt[N],to[N],tot;
bool vis[N];
struct Seg_tree
{
int val[4000000],ls[4000000],rs[4000000],sz;
void insert(int&x,int y,int l,int r,int p)
{
x = ++sz;
val[x] = val[y];
ls[x] = ls[y]; rs[x] = rs[y];
++val[x];
if(l == r) return;
int mid = l + r >> 1;
if(p <= mid) insert(ls[x],ls[y],l,mid,p);
else insert(rs[x],rs[y],mid+1,r,p);
}
int query(int x,int l,int r,int p)
{
if(r <= p) return val[x];
int mid = l + r>> 1;
if(p > mid) return val[ls[x]] + query(rs[x],mid+1,r,p);
else return query(ls[x],l,mid,p);
}
}seg;
inline void add(int x,int y)
{
to[tot] = y;
nxt[tot] = head[x];
head[x] = tot++;
}
int deep[N],size[N],hson[N],top[N],id[N],idx[N],sz;
void dfs1(int x)
{
size[x] = 1;
for(register int i = head[x] ;~i;i = nxt[i])
{
deep[to[i]] = deep[x] + 1;
dfs1(to[i]);
size[x] += size[to[i]];
if(size[to[i]] > size[hson[x]])
hson[x] = to[i];
}
}
void dfs2(int x,int t)
{
top[x] = t;
id[x] = ++ sz;idx[sz] = x;
if(hson[x]) dfs2(hson[x],t);
for(register int i = head[x];~i;i=nxt[i])
if(to[i] != hson[x])
dfs2(to[i],to[i]);
}
int find(int x,int y)
{
int ans = 0;
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]]) swap(x,y);
ans += deep[x] - deep[top[x]] + 1;
x = f[top[x]];
}
if(deep[x] < deep[y]) swap(x,y);
return ans + deep[x] - deep[y] + 1;
}
int query(int x,int y,int c)
{
if(c < 1) return 0;
int ans = 0;
while(top[x] != top[y])
{
if(deep[top[x]] < deep[top[y]]) swap(x,y);
ans += seg.query(rt[id[x]],1,N,c) - seg.query(rt[id[top[x]] - 1],1,N,c);
x = f[top[x]];
}
if(deep[x] < deep[y]) swap(x,y);
return ans + seg.query(rt[id[x]],1,N,c) - seg.query(rt[id[y] - 1],1,N,c);
}
int u[N],v[N],ti[N];
int main()
{
memset(head,-1,sizeof head);
read(n);
rep(i,1,n)
{
read(f[i]);
if(f[i]) add(f[i],i);
else root = i;
}
dfs1(root);
dfs2(root,root);
rep(i,1,n) w[i] = N ;
int q;
read(q);
rep(i,1,q)
{
int op,a;
read(op);
if(op == 1)
{
read(u[i]); read(v[i]); read(ti[i]);
ti[i] = i - ti[i] - 1;
}
else
{
read(a);
if(vis[a]) continue;
vis[a] = 1; w[a] = i;
}
}
rep(i,1,n) seg.insert(rt[i],rt[i-1],1,N,w[idx[i]]);
rep(i,1,q) if(u[i]) printf("%d %d\n",find(u[i],v[i]),query(u[i],v[i],ti[i]));
return 0;
}