1466.祖先極值
Time Limit: 5000 MS Memory Limit: 131072 K
Total Submissions: 153 (39 users) Accepted: 43 (25 users)
[ My Solution]
Description
在一棵有向樹中, 若節點u至節點v之間有一條有向邊, 則我們稱u為v的父節點, 也可以稱作1祖先節點。所謂節點v的k祖先節點, 指的是節點v的父節點的k-1祖先節點。現在, 給定你一棵以0為根節點的樹, 樹上的每個節點都有一個值, 你需要能快速的回答出從節點v至它的k祖先節點所經過的所有節點中(即v節點、v節點的1祖先、...、v節點的k-1祖先、v節點的k祖先), 值最大的節點的值的為多少? 其中我們默認0號節點的值為0。
Input
輸入的第一行有一個正整數n (n <= 100,000), 接下來的一行有n個整數ai(1 <= i <= n, 1 <= ai <= 1,000,000,000), 第i個數字代表了第i號節點上的數值。再接下來的一行有n個正整數bi(1 <= i <= n, 0 <= bi < i), 第i個數字代表了第i號節點的父節點的為bi。再接下來有一個整數m (1 <= m <= 100,000), 代表了詢問的次數, 接下來的m行, 每行有2個整數k, v (1 <= k <= n, 1 <= v <= n), 代表了詢問, 從v節點到它的k祖先所經歷的所有節點中的最大值。
Output
對於每次詢問, 若v節點不存在k祖先, 則輸出一行"Wrong request", 否則輸出一個整數, 代表了從v節點到它的k祖先所經歷的所有節點中的最大值。
Sample Input
5
1 2 2 1 3
0 0 1 1 2
4
1 4
2 2
2 3
1 5
Sample Output
1
Wrong request
2
3
唉,我真是太笨了,看了別人的代碼才會做,就是以樹的高度作為區間查詢
妹的,苦逼的調試
[cpp]
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define N 100010
#define l(i) i<<1
#define r(i) i<<1|1
struct node{
int l,r,mx;
}T[N*4];
int mx;
struct Data{
int x,id;
};
int v[N],ans[N];//值,答案
vector<Data>a[N];
vector<int>son[N];
void build(int l,int r,int k){
T[k].l=l;
T[k].r=r;
T[k].mx=0;
if(l==r)return;
int mid=(l+r)/2;
build(l,mid,l(k));
build(mid+1,r,r(k));
}
int insert(int d,int k,int v){//值k插入區間[d,d]
if(T[k].l==T[k].r)return T[k].mx=v;
int ll=l(k);
int rr=r(k);
if(T[ll].r>=d)insert(d,ll,v);//往左
else if(T[rr].l<=d) insert(d,rr,v);//往右
return T[k].mx=max(T[ll].mx,T[rr].mx);
}
void query(int l,int r,int k){//查詢區間[l,r]
if(T[k].l==l&&T[k].r==r){
mx=max(mx,T[k].mx);
return;
}
int ll=l(k);
int rr=r(k);
if(T[ll].r>=r)query(l,r,ll);//往左
else if(T[rr].l<=l)query(l,r,rr);//往右
else{
query(l,T[ll].r,ll);//往左
query(T[rr].l,r,rr);//往右
}
}
void dfs(int x,int d){
int i,j,k;
insert(d,1,v[x]);//插入v
//cout<<"插入"<<x<<" "<<v[x]<<endl;
for(i=0;i<a[x].size();i++){//查詢x結點
k=d-a[x][i].x;
mx=-1;
if(k>=0)query(k,d,1);
ans[a[x][i].id]=mx;
//cout<<x<<" "<<k<<" "<<d<<" "<<mx<<endl;
}
for(i=0;i<son[x].size();i++)//遍歷兒子
dfs(son[x][i],d+1);//遞歸遍歷
}
int main(){
int n,i,j,k;
v[0]=0;
struct Data s;
while(scanf("%d",&n)!=EOF){
memset(a,0,sizeof(a));
memset(son,0,sizeof(son));
build(0,n-1,1);//建立空樹
for(i=1;i<=n;i++)scanf("%d",&v[i]);
for(i=1;i<=n;i++){
scanf("%d",&j);
son[j].push_back(i);//i是j的兒子
}
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d%d",&j,&k);
s.x=j;s.id=i;
a[k].push_back(s);
}
/*for(i=0;i<=n;i++){
cout<<i<<":";
for(j=0;j<son[i].size();j++){
cout<<son[i][j]<<" ";
}
cout<<endl;
}*/
dfs(0,0);//從根遍歷到最後
for(i=0;i<n;i++)
if(ans[i]==-1)printf("Wrong request\n");
else printf("%d\n",ans[i]);
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define N 100010
#define l(i) i<<1
#define r(i) i<<1|1
struct node{
int l,r,mx;
}T[N*4];
int mx;
struct Data{
int x,id;
};
int v[N],ans[N];//值,答案
vector<Data>a[N];
vector<int>son[N];
void build(int l,int r,int k){
T[k].l=l;
T[k].r=r;
T[k].mx=0;
if(l==r)return;
int mid=(l+r)/2;
build(l,mid,l(k));
build(mid+1,r,r(k));
}
int insert(int d,int k,int v){//值k插入區間[d,d]
if(T[k].l==T[k].r)return T[k].mx=v;
int ll=l(k);
int rr=r(k);
if(T[ll].r>=d)insert(d,ll,v);//往左
else if(T[rr].l<=d) insert(d,rr,v);//往右
return T[k].mx=max(T[ll].mx,T[rr].mx);
}
void query(int l,int r,int k){//查詢區間[l,r]
if(T[k].l==l&&T[k].r==r){
mx=max(mx,T[k].mx);
return;
}
int ll=l(k);
int rr=r(k);
if(T[ll].r>=r)query(l,r,ll);//往左
else if(T[rr].l<=l)query(l,r,rr);//往右
else{
query(l,T[ll].r,ll);//往左
query(T[rr].l,r,rr);//往右
}
}
void dfs(int x,int d){
int i,j,k;
insert(d,1,v[x]);//插入v
//cout<<"插入"<<x<<" "<<v[x]<<endl;
for(i=0;i<a[x].size();i++){//查詢x結點
k=d-a[x][i].x;
mx=-1;
if(k>=0)query(k,d,1);
ans[a[x][i].id]=mx;
//cout<<x<<" "<<k<<" "<<d<<" "<<mx<<endl;
}
for(i=0;i<son[x].size();i++)//遍歷兒子
dfs(son[x][i],d+1);//遞歸遍歷
}
int main(){
int n,i,j,k;
v[0]=0;
struct Data s;
while(scanf("%d",&n)!=EOF){
memset(a,0,sizeof(a));
memset(son,0,sizeof(son));
build(0,n-1,1);//建立空樹
for(i=1;i<=n;i++)scanf("%d",&v[i]);
for(i=1;i<=n;i++){
scanf("%d",&j);
son[j].push_back(i);//i是j的兒子
}
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d%d",&j,&k);
s.x=j;s.id=i;
a[k].push_back(s);
}
/*for(i=0;i<=n;i++){
cout<<i<<":";
for(j=0;j<son[i].size();j++){
cout<<son[i][j]<<" ";
}
cout<<endl;
}*/
dfs(0,0);//從根遍歷到最後
for(i=0;i<n;i++)
if(ans[i]==-1)printf("Wrong request\n");
else printf("%d\n",ans[i]);
}
return 0;
}