• 換根
• 修改點權
• 查詢子樹最小值
接下來n行,每行兩個整數f,v,第i+1行的兩個數表示點i的父親和點i的權。保證f < i。如 果f = 0,那麼i爲根。輸入數據保證只有i = 1時,f = 0。
接下來 m 行,爲以下格式中的一種:
• V x y表示把點x的權改爲y
• E x 表示把有根樹的根改爲點 x
• Q x 表示查詢點 x 的子樹最小值
0 1
1 2
1 3
Q 1
V 1 6
Q 1
V 2 5
Q 1
V 3 4
Q 1
2
3
4
題目大意就是給你一棵樹,支持換根、修改點權、求一個點的子樹的最小值。
對於這道題,如果沒有換根操作,就直接上RMQ。
然而有了換根,我們可以先以1號點爲根處理出這棵樹的dfs序用線段樹來維護一段dfs序的最小值,修改點權就不說了。
對於每個查詢
設查詢的點X;
設此時根爲R;
設L[X]代表X在dfs序中第一次出現的位置
設R[X]代表X在dfs序中第一次出現的位置
如圖的一棵樹
1:當X等於R時 比如X=R=1
直接輸出整棵樹的最小值。
2:當R不在X的子樹中 比如X=2 R=3
明顯就是X的子樹中的最小值
即爲L[X]到R[X]的最小值
3:當X是R的祖先時
首先確定包含點的範圍:
舉兩個例子:當X=2、R=4時是1、2、3、5,當X=1、R=4時是1、3。
通過這兩個例子,我們可以看出包含的範圍就是整棵樹除去E所在的子樹(E是X的兒子,也是R的祖先)。
那麼答案就是L[1]到L[E]-1與R[E]+1到R[1]的最小值
(這一點要仔細想想,當初也是花了好久才弄懂)
最後說一下幾個要注意的地方吧
求dfs序,不能直接dfs,會爆棧,所以。。。。手動棧吧
找E的時候不能一步一步往上跳,用倍增吧
Ps:其實上面兩點都不要管就可以過原始數據,只是我們oj喪心病狂處處卡人啊。。。。
轉自http://blog.csdn.net/abc473848880/article/details/13503533
但代碼不一樣哦
附代碼
#include<cmath>
#include<stack>
#include<cstdio>
#include<vector>
#include<utility>
using namespace std;
typedef pair<int,int> PII;
class Dread{
public:
int Int() { int x;read(x);return x; }
char Char() { char ch;read(ch);return ch; }
private:
bool isdigit(char ch){ return ('0'<=ch && ch<='9'); }
bool isalpha(char ch){ return ('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z'); }
void read(int &x){
char ch;int tmp=0;
while (ch=getchar()) if (isdigit(ch)) break;
for (; isdigit(ch); ch=getchar()) tmp=tmp*10+ch-'0';
x=tmp;
}
void read(char &ch){
while (ch=getchar()) if (isalpha(ch)) break;
}
}READ;
void swap(int &a,int &b){ int t=a;a=b;b=t; }
inline int min(int a,int b){ return a<b?a:b; }
const int N_MAX=100000+10,M_MAX=200000+10,K_MAX=20;
int now[N_MAX],pre[M_MAX],son[M_MAX],tot=0;
inline void add(int a,int b){ pre[++tot]=now[a];now[a]=tot;son[tot]=b; }
int N,Que,rt=1,val[N_MAX];
struct Ttree{
struct SysInfo{
int id,edge; //id?????????? ,edge????????????????
SysInfo(){}
SysInfo(int _id,int _edge):id(_id),edge(_edge){}
};
vector<int> dfn;stack<SysInfo> stk;
int anc[N_MAX][K_MAX],dep[N_MAX];PII app[N_MAX];
void dfs(){
stk.push(SysInfo(1,-1));dfn.push_back(1);app[1].first=dfn.size()-1;
while (!stk.empty()){
SysInfo top=stk.top();int p;
for (p=top.edge==-1?now[top.id]:pre[top.edge]; p; p=pre[p]){
stk.pop();stk.push(SysInfo(top.id,p));
dep[son[p]]=dep[top.id]+1;
anc[son[p]][0]=top.id;
for (int tmp=top.id,k=0; anc[tmp][k]; ++k){
anc[son[p]][k+1]=anc[tmp][k];
tmp=anc[tmp][k];
}
stk.push(SysInfo(son[p],-1));
dfn.push_back(son[p]);
app[son[p]].first=dfn.size()-1;
break;
}
if (!p) dfn.push_back(top.id),stk.pop(),app[top.id].second=dfn.size()-1;
}
}
void dfs(int x){ //????????????????????????
dfn.push_back(x);app[x].first=dfn.size()-1;
for (int p=now[x]; p; p=pre[p]){
dep[son[p]]=dep[x]+1;
anc[son[p]][0]=x;
for (int tmp=x,k=0; anc[tmp][k]; ++k){
anc[son[p]][k+1]=anc[tmp][k];
tmp=anc[tmp][k];
}
dfs(son[p]);
}
dfn.push_back(x);app[x].second=dfn.size()-1;
}
int Lca(int x,int y){
if (x==y) return x;
if (dep[x]<dep[y]) swap(x,y);
int xdep=dep[x]-dep[y];
for (int k=0; xdep; ++k){
if (xdep%2) x=anc[x][k];
xdep/=2;
}
if (x==y) return x;
for (int k=0; x!=y; ){
if (anc[x][k]!=anc[y][k] || (anc[x][k]==anc[y][k] && !k)){
x=anc[x][k];y=anc[y][k];
++k;
}
else --k;
}
return x;
}
int find(int x,int y){ //????x????y????????????????
int xdep=dep[x]-dep[y]-1;
for (int k=0; xdep; ++k){
if (xdep%2) x=anc[x][k];
xdep/=2;
}
return x;
}
}TREE;
class Tseg{
public:
int size;
void Build() { build(1,0,size=TREE.dfn.size()-1); }
int Query(int l,int r) { return query(1,0,size,l,r); }
void Modify(int x,int y){ modify(1,0,size,x,y); }
private:
int t[16*N_MAX];
#define ls p*2
#define rs p*2+1
#define Lson p*2,l,mid
#define Rson p*2+1,mid+1,r
void update(int p){ t[p]=min(t[ls],t[rs]); }
void build(int p,int l,int r){
if (l==r){
t[p]=val[TREE.dfn[l]];
return;
}
int mid=(l+r)/2;
build(Lson);build(Rson);
update(p);
}
int query(int p,int l,int r,int fir,int lst){
if (l==fir && r==lst) return t[p];
int mid=(l+r)/2;
if (lst<=mid) return query(Lson,fir,lst);
else if (fir>mid) return query(Rson,fir,lst);
else return min(query(Lson,fir,mid),query(Rson,mid+1,lst));
}
void modify(int p,int l,int r,int pos,int val){
if (l==pos && r==pos){ t[p]=val; return; }
int mid=(l+r)/2;
if (pos<=mid) modify(Lson,pos,val);
else modify(Rson,pos,val);
update(p);
}
}SEG;
int main(){
N=READ.Int();Que=READ.Int();
for (int i=1; i<=N; ++i){
int fa=READ.Int();val[i]=READ.Int();
if (fa) add(fa,i);
}
TREE.dfs();
SEG.Build();
for (int i=1; i<=Que; ++i){
char opt=READ.Char();
if (opt=='Q'){
int x=READ.Int();
if (x==rt) printf("%d\n", SEG.Query(0,SEG.size));
else{
int ancestor=TREE.Lca(rt,x);
if (ancestor!=x) printf("%d\n", SEG.Query(TREE.app[x].first,TREE.app[x].second));
else{
int far=TREE.find(rt,x);
// printf(" %d %d %d\n",far,TREE.app[far].first-1,TREE.app[far].second+1);
printf("%d\n", min(SEG.Query(0,TREE.app[far].first-1),
SEG.Query(TREE.app[far].second+1,SEG.size)));
}
}
}
else if (opt=='E'){
int newrt=READ.Int();
rt=newrt;
}
else{
int x=READ.Int(),y=READ.Int();
SEG.Modify(TREE.app[x].first,y);
SEG.Modify(TREE.app[x].second,y);
}
}
//system("pause");
return 0;
}