在
berland,有n
個城堡。
每個城堡恰好屬於乙個領主。不同的城堡屬於不同的領主。在所有領主中有乙個是國王,其他的每個領主都直接隸屬於另一位領主,並且間接隸屬於國王。一位領主可以擁有任意數量的下屬。這些城堡被一些雙向的道路連線。兩個城堡是連線的當且僅當他們的主人中一位直接隸屬於另一位。
每一年,在
berland
會發生以下兩件事中的一件:
1.野蠻人攻擊了城堡
c。這是城堡
c第一次也會是最後一次被攻擊,因為野蠻人從來不攻擊同一座城堡超過一次。
2.乙個騎士從城堡
a出發前往到城堡
b。騎士從不重複經過同一座城堡,因此他的路線是唯一確定的。
現在考慮第二類事件。由於從城堡a到
b的路途遙遠,每個騎士會在他經過的某個城堡停下來休息一次。根據規則,騎士不能停留在第
y 年以後受到過攻擊的城堡中。所以,騎士選擇了途徑的第
k個從第
y+1
年開始到現在(當時)沒有被攻擊過的城堡(不算城堡a和
b)。你,偉大的歷史學家,知道
berland
歷史上的所有
m個事件。請你計算,每個騎士是在哪個城堡休息的。如果在從城堡
a到城堡
b的路上少於
k座城堡,那麼你可以斷定有關這個騎士的記載是有誤的。
第一行包含乙個整數
n,表示城堡數目。
第二行包含
n個整數,依次表示編號為
1...n
的城堡領主的上級。特別的,國王沒有上級,故用
0 表示。
第三行包含乙個整數
m,表示事件數目。
接下來m
行,每行描述乙個事件:
若是第1
類事件,則包含兩個整數,依次是1,
ci;若是第2
類事件,則包含五個整數,依次是2,
ai,bi,
ki,yi。
輸出若干行,每行乙個整數,依次表示每個騎士休息的城堡編號。若騎士不可能休息,則輸出-1。
3
0 1 2
52 1 3 1 0
1 22 1 3 1 0
2 1 3 1 1
2 1 3 1 2
2
-1-1
2
【資料規模和約定】
20%的資料:
1 ≤ n, m ≤ 1000;另有
30%的資料:有且僅有乙個領主沒有下屬;
100%
的資料:
1 ≤ n, m ≤ 105,
1 ≤ ai, bi, ci, ki ≤ n
,0 ≤ yi < i
,每個事件中
ai ≠ bi
。2014北京省選集訓day2
solution
樹剖,轉化為區間問題
對於每乙個時間開一棵主席樹,下標1~n,表示i是否被毀壞
對於詢問,取出第y棵樹和現在的樹
如果有變動,就不能住。
比較煩的就是從b到lca的路徑要求top-k+1大,
因為它是倒過來的
還有ab不能住,需要加一加
#include#include#include#include#include#include#define maxn 100005
using namespace std;
int n,m,head[maxn],t1,t2,tot,dfn[maxn],deep[maxn],son[maxn],size[maxn];
int top[maxn],fa[maxn],sc,total,dy[maxn],op,root[maxn],t,a,b;
int lca,a1,b1,li,ri,rk,las,rak,num1,num2,ff;
struct notree[maxn*23];
struct nodee[maxn*2];
void lj(int t1,int t2)
void dfs1(int k,int fath)
}size[k]=sz+1;son[k]=gp;
}void dfs2(int k)
for(int i=head[k];i;i=e[i].nex)
}}void wh(int k)
void dfs(int &k,int la,int l,int r,int pl)
tree[k].ls=tree[la].ls,tree[k].rs=tree[la].rs;
int mid=l+r>>1;
if(pl<=mid)dfs(tree[k].ls,tree[la].ls,l,mid,pl);
else dfs(tree[k].rs,tree[la].rs,mid+1,r,pl);
wh(k);
}int ch(int k,int la,int l,int r)
int mid=l+r>>1;
int su=0;
if(li<=mid)su+=ch(tree[k].ls,tree[la].ls,l,mid);
if(ri>mid)su+=ch(tree[k].rs,tree[la].rs,mid+1,r);
return su;
}int ask(int k,int la,int l,int r,int fs)
else return ask(tree[k].ls,tree[la].ls,l,mid,fs);
}int main()
dfs1(1,0);top[1]=1;dfs2(1);
cin>>m;
for(int i=1;i<=m;i++)
else
else rk-=num;
a=fa[t1],t1=top[a];
}if(fl)continue;
li=dfn[lca],ri=dfn[a];
num=ch(root[i],root[las],1,n);
if(num>=rk)
// right
fl=0;rk=rak;
b=b1,t2=top[b];
while(t2!=top[lca])
else rk-=num;
b=fa[t2],t2=top[b];
}if(fl)continue;
li=dfn[lca],ri=dfn[b];
num=ch(root[i],root[las],1,n);
if(num>=rk)}}
return 0;
}
posted @
2018-08-30 19:51
liankewei 閱讀(
...)
編輯收藏
5055 樹上路徑
給定一顆 n 個結點的無根樹,每個點有乙個點權,定義一條路徑的價值為路徑上的點權和 路徑的點權最大值。給定引數 p,求有多少不同的樹上簡單路徑,滿足它的價值恰好是 p 的倍數。data constraint n 105,p 107 考慮點分治。對於當前的分治重心,把所有以它為起點的路徑取出來,按照路...
題解 樹上路徑
一棵樹的構造過程為 首先以1號點為根,然後依次加入2 n號點。加入i號點時,在1 i 1點中選擇乙個點為f i 將i號點與其相連線。yuri想要求出,每次加點之後路上的最長路徑長度。第一行乙個整數n,表示樹的節點個數。第二行n 1個整數,第i個整數表示f i 1 一行n 1個整數,分別表示加完2 n...
JZOJ5055 樹上路徑
給定一棵 n 個節點的無根樹,每個點都有乙個非負整數的權值va li,定義一條路徑的價值為路徑上的點權和減去路徑的點權最大值。給定引數 p 請求出樹上有多少條價值是 p的倍數的路徑。注意 單點也算路徑。並且路徑 u v 和 v u 只算一次。1 n 105 1 p 107,0 va li 10 9 ...