这题并不难想,但是很难写。
首先先转化为开区间,然后一个就是挂左链,一个是挂右链。
然后变成了一个点与左链上挂的点的距离的问题。
然后就分讨吧!
此处省略一万字。
写完之后,编译了一下程序,电脑死机了。
然后发现自己CMLE了。(CMLE,即编译器内存超限)
原因是在c++11标准下struct内二维数组开太大了,过了一会发现是g++版本太低的锅,然而uoj版本也很低。
就不得不套上了一个诡异的东西,变长了也变慢了,可是终于能过编译了。
uoj 暂时代码长度rank 倒1,运行时间rank 倒2,惨。
#include <bits/stdc++.h>
using namespace std;
namespace Fastio{
const int BUFF=7e5;
char ch[BUFF],*l=ch,*r=ch;
char gc(){
if (l==r) l=ch,r=l+fread(ch,1,BUFF,stdin);
if (l==r) return EOF;
return *(l++);
}
void read(int &x) {
x = 0;
char ch = gc();
while(!isdigit(ch)) ch = gc();
while(isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
}
};
using namespace Fastio;
namespace container{
template<class T,size_t BLOCK_SIZE>
class myarray{
struct period{
T a[BLOCK_SIZE];
period* ne=NULL;
period(){
}
period(const T &v){
fill(a,a+BLOCK_SIZE,v);
}
};
period *Be;
size_t Sz;
class iterator{
period *ip;
size_t pos;
myarray *po;
public:
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef ptrdiff_t difference_type;
iterator():ip(nullptr),pos(0),po(nullptr){
}
iterator(const iterator &it){
(*this)=it;
}
iterator(period * const &ip,const size_t &pos,myarray * const &po):ip(ip),pos(pos),po(po){
}
bool operator !=(const iterator &it) const{
return ip!=it.ip||pos!=it.pos;
}
bool operator ==(const iterator &it) const{
return ip==it.ip&&pos==it.pos;
}
iterator operator ++(){
if (++pos==BLOCK_SIZE&&ip->ne!=NULL){
ip=ip->ne;
pos=0;
}
return *this;
}
const iterator operator ++(int){
iterator tmp(*this);
if (++pos==BLOCK_SIZE&&ip->ne!=NULL){
ip=ip->ne;
pos=0;
}
return tmp;
}
iterator operator --(){
if (pos){
--pos;
return (*this);
}
period *tBe=po->Be;
while (tBe->ne!=ip) tBe=tBe->ne;
ip=tBe;
pos=BLOCK_SIZE-1;
return (*this);
}
const iterator operator --(int){
iterator tmp(*this);
if (pos){
--pos;
return tmp;
}
period *tBe=po->Be;
while (tBe->ne!=ip) tBe=tBe->ne;
ip=tBe;
pos=BLOCK_SIZE-1;
return tmp;
}
iterator operator +(const size_t &len) const{
//ip!=NULL BUG
if (BLOCK_SIZE>pos+len) return iterator(ip,pos+len,po);
size_t tmp=len-(BLOCK_SIZE-1-pos);
if (ip->ne==NULL) return iterator(ip,BLOCK_SIZE,po);
period *tip=ip->ne;
while (tmp>BLOCK_SIZE){
if (tip->ne==NULL) return iterator(tip,BLOCK_SIZE,po);
tip=tip->ne;
tmp-=BLOCK_SIZE;
}
return iterator(tip,tmp-1,po);
}
iterator operator +=(const size_t &len){
return ((*this)=(*this)+len);
}
size_t operator -(const iterator &it) const{
//only
if (ip==it.ip) return pos-it.pos;
period *tmp=it.ip->ne;
size_t ret=BLOCK_SIZE-it.pos;
while (tmp!=ip){
ret+=BLOCK_SIZE;
tmp=tmp->ne;
}
return ret+pos;
}
iterator operator -(const size_t &len) const{
return (po->begin()+((*this)-(po->begin())-len));
}
iterator operator -=(const size_t &len){
return ((*this)=(*this)-len);
}
bool operator <(const iterator &it) const{
//same father
return ((*this)-po->begin())<(it-(po->begin()));
}
bool operator <=(const iterator &it) const{
//same father
return ((*this)-po->begin())<=(it-(po->begin()));
}
T & operator *() const{
return ip->a[pos];
}
};
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
myarray(){
Be=NULL;
Sz=0;
}
myarray(const size_t &sz){
construct(sz);
}
myarray(const size_t &sz,const T &v){
construct(sz,v);
}
~myarray(){
myfree(Be);
}
myarray(const myarray &rhs){
if (this==&rhs) return;
construct(rhs.size());
auto j=begin();
for (auto it=rhs.begin(); it!=rhs.end(); ++it) *(j++)=(*it);
}
myarray(const initializer_list<T> &args){
construct(args.size());
auto j=begin();
for (auto it=args.begin(); it!=args.end(); ++it) *(j++)=(*it);
}
myarray& operator =(const myarray &rhs){
if (this==&rhs) return (*this);
myfree(Be);
construct(rhs.size());
auto j=begin();
for (auto it=rhs.begin(); it!=rhs.end(); ++it) *(j++)=(*it);
return *this;
}
void myfree(period * const &Be){
period *tBe=Be,*tmp;
while (tBe!=NULL){
tmp=tBe->ne;
delete tBe;
tBe=tmp;
}
}
void construct(const size_t &sz){
Be=new period();//slow but safe
Sz=sz;
size_t tSz=sz;
period *tBe=Be;
while (tSz>BLOCK_SIZE){
tBe=(tBe->ne=new period);
tSz-=BLOCK_SIZE;
}
}
void construct(const size_t &sz,const T &v){
Be=new period(v);
Sz=sz;
size_t tSz=sz;
period *tBe=Be;
while (tSz>BLOCK_SIZE){
tBe=(tBe->ne=new period);
tSz-=BLOCK_SIZE;
}
}
iterator begin() const{
return iterator(Be,0,(myarray*)this);
}
iterator end() const{
//Slow And Dangerous
if (Be==NULL) return iterator(NULL,0,(myarray*)this);
period *tBe=Be;
while (tBe->ne!=NULL) tBe=tBe->ne;
return iterator(tBe,((int)Sz-1)%(int)BLOCK_SIZE+1,(myarray*)this);
}
void push_back(const T &v){
if (Be==NULL){
Be=new period;
Be->a[Sz++]=v;
return;
}
period *tBe=Be;
while (tBe->ne!=NULL) tBe=tBe->ne;
size_t tSz=(Sz++)%BLOCK_SIZE;
if (tSz==0) tBe=(tBe->ne=new period);
tBe->a[tSz]=v;
}
void pop_back(){
if ((--Sz)%BLOCK_SIZE) return;
if (Sz==0){
delete Be;
Be=NULL;
return;
}
period *tBe=Be;
while (tBe->ne->ne!=NULL) tBe=tBe->ne;
delete tBe->ne;
tBe->ne=NULL;
}
T& operator [](const size_t &pos) const{
size_t tpos=pos;
for (period* i=Be; i!=NULL; i=i->ne)
if (tpos<BLOCK_SIZE) return i->a[tpos];
else tpos-=BLOCK_SIZE;
throw;
}
T& front() const{
//unusual
return Be->a[0];
}
T& back() const{
return *(--end());
}
size_t size() const{
return Sz;
}
bool empty() const{
return Sz==0;
}
template<class U>
struct iterator_traits{
typedef typename U::value_type value_type;
typedef typename U::iterator_category iterator_category;
typedef typename U::difference_type difference_type;
typedef typename U::pointer pointer;
typedef typename U::reference reference;
};
};
}
template<class T,size_t BLOCK_SIZE>
using arr=container::myarray<T,BLOCK_SIZE>;
typedef long long ll;
typedef pair<ll,int> p;
const int N=200005;
int nodenum,fa[N*2][20];
int son[N*2][2];
int dep[N*2];
int clk,dfn[N*2],en[N*2];
void Rebuild(){
for (int j=1; j<=17; ++j)
for (int i=1; i<=nodenum; ++i)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
int upto(const int &x,const int &y){
int tmp=x;
int dis=dep[tmp]-dep[y]-1;
for (int j=17; j>=0; --j)
if ((dis>>j)&1) tmp=fa[tmp][j];
return tmp;
}
bool inrange(const int &x){
return x>=1&&x<=nodenum;
}
int Getlca(int x,int y){
if (!inrange(x)) return 0;
if (!inrange(y)) return 0;
if (dep[x]>dep[y]) swap(x,y);
for (int j=17; j>=0; --j) if (fa[y][j]&&dep[x]<=dep[fa[y][j]]) y=fa[y][j];
if (x==y) return x;
for (int j=17; j>=0; --j)
if (fa[x][j]!=fa[y][j]){
x=fa[x][j];
y=fa[y][j];
}
return fa[x][0];
}
p operator +(const p &A,const p &B){
return {A.first+B.first,A.second+B.second};
}
namespace Pre{
int tim,n,mid[N],trans[N*2];
void Divide(int x,int l,int r){
//cerr<<"Divide"<<x<<" "<<l<<" "<<r<<endl;
if (l==r) return;
int curtim=tim;
int now=curtim+n;
trans[++*trans]=now;
if (l==mid[curtim]){
son[now][0]=l;
trans[++*trans]=l;
}
else{
son[now][0]=n+tim+1;
Divide(++tim,l,mid[curtim]);
}
if (mid[curtim]+1==r){
son[now][1]=r;
trans[++*trans]=r;
}
else{
son[now][1]=n+tim+1;
Divide(++tim,mid[curtim]+1,r);
}
}
void Build_tree(){
scanf("%d",&n);
for (int i=1; i<n; ++i){
scanf("%d",&mid[i]);
}
nodenum=n+n-1;
Divide(tim=1,1,n);
}
}
struct line{
arr<p,18> sum[N*2];
line(){
for (int i=1; i<N*2; ++i) sum[i]=arr<p,18>(1);
}
void Ups(){
for (int i=1; i<=nodenum; ++i){
p tmp=sum[i][0];
sum[i]=arr<p,18>(18);
sum[i][0]=tmp;
}
}
void Append(int x){
sum[x][0]=p({dep[x],1});
}
void Rebuild(){
for (int j=1; j<=17; ++j)
for (int i=1; i<=nodenum; ++i){
int faf=fa[i][j-1];//grand father
if (!faf) continue;
sum[i][j]=sum[i][j-1]+sum[faf][j-1];
}
}
p cat_chain(const int &x,const int &y){
int tmp=x;
int dis=dep[tmp]-dep[y];
p ret=p({0ll,0});
for (int j=17; j>=0; --j)
if ((dis>>j)&1){
ret=ret+sum[tmp][j];
tmp=fa[tmp][j];
}
return ret;
}
bool is_child(const int &a,const int &b){
//a==b 1
return dfn[b]<=dfn[a]&&en[a]<=en[b];
}
bool linear_relative_in_order(const int &a,const int &b,const int &c){
return is_child(a,b)&&is_child(b,c);
}
ll Downchain(int x,int top,int y,int d){
//cerr<<"Downchain"<<x<<" "<<top<<" "<<y<<endl;
if (dep[x]<dep[top]) return 0;
p tmp=cat_chain(x,top);
int lca=Getlca(top,y);
ll ret=tmp.first+(ll)tmp.second*dep[y];
ret-=2ll*tmp.second*dep[lca];
if (inrange(son[top][d^1])){
int plca=Getlca(son[top][d^1],y);
ret+=2*dep[lca];
ret-=2*dep[plca];
}
//cerr<<"Ret"<<ret<<endl;
return ret;
}
ll Upchain(int x,int top,int y){
//cerr<<"Upchain"<<x<<" "<<top<<" "<<y<<endl;
if (dep[x]<dep[top]) return 0;
p tmp=cat_chain(x,top);
ll ret=tmp.first+(ll)tmp.second*dep[y];
ret-=2ll*(tmp.first-tmp.second);//the sum of lca's dep
//cerr<<"Ret"<<ret<<endl;
return ret;
}
int Dis(int x,int y){
//cerr<<"Dis"<<x<<" "<<y<<endl;
return dep[x]+dep[y]-2*dep[Getlca(x,y)];
}
ll Askdistance(int x,int top,int y,int d){
//cerr<<"Askdistance"<<x<<" "<<top<<" "<<y<<endl;
//True function
if (x<1||x>Pre::n) return 0;
int ignore_pos=Getlca(x,y);
//cerr<<"IGP"<<ignore_pos<<endl;
if (linear_relative_in_order(x,ignore_pos,top)){
return Downchain(x,ignore_pos,y,d)+Upchain(ignore_pos,top,y);
}
if (is_child(top,ignore_pos)) return Downchain(x,top,y,d);
return Upchain(x,top,y);
}
}le,ri;
//le 左链
//ri 右链
void Dfs(int x,int fa,bool iri){
//cerr<<"Dfs"<<x<<" "<<fa<<" "<<iri<<endl;
if (!x) return;
dfn[x]=++clk;
dep[x]=dep[fa]+1;
::fa[x][0]=fa;
if (fa){
if (iri) ri.Append(x); else le.Append(x);
}
Dfs(son[x][0],x,0);
Dfs(son[x][1],x,1);
en[x]=clk;
}
int main(){
Pre::Build_tree();
Dfs(Pre::n+1,0,0);
le.Ups();
ri.Ups();
Rebuild();
le.Rebuild();
ri.Rebuild();
int m;
read(m);
for (int i=1; i<=m; ++i){
int u,l,r;
read(u);
read(l);
read(r);
u=Pre::trans[u];
--l;
++r;
if (l==0&&r==Pre::n+1){
cout<<le.Dis(Pre::n+1,u)<<'
';
continue;
}
//cerr<<u<<" "<<l<<" "<<r<<endl;
int lca=(l<1||l>Pre::n||r<1||r>Pre::n?0:Getlca(l,r));
//cerr<<"lca"<<lca<<endl;
cout<<le.Askdistance(l,upto(l,lca),u,0)+ri.Askdistance(r,upto(r,lca),u,1)<<'
';//bug here
}
}