ray 樂忠於旅遊,這次他來到了t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說, t 城中只有n − 1 座橋。
ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥濘,令人煩躁。於是,他給每座橋定義乙個愉悅度w,也就是說,ray 經過這座橋會增加w 的愉悅度,這或許是正的也可能是負的。有時,ray 看待同一座橋的心情也會發生改變。
現在,ray 想讓你幫他計算從u 景點到v 景點能獲得的總愉悅度。有時,他還想知道某段路上最美麗的橋所提供的最大愉悅度,或是某段路上最糟糕的一座橋提供的最低愉悅度。
輸入格式:
輸入的第一行包含乙個整數n,表示t 城中的景點個數。景點編號為 0...n − 1。
接下來n − 1 行,每行三個整數u、v 和w,表示有一條u 到v,使 ray 愉悅度增加w 的橋。橋的編號為1...n − 1。|w| <= 1000。 輸入的第n + 1 行包含乙個整數m,表示ray 的運算元目。
接下來有m 行,每行描述了乙個操作,操作有如下五種形式:
測試資料保證,任意時刻,ray 對於經過每一座橋的愉悅度的絕對值小於等於1000。
題意:邊權樹鏈剖分 並維護 最大值最小值 求和 單點修改 區間取相反數
首先要考慮將邊權轉化為點權 如果轉到父節點的話 會出現多個邊在乙個點的情況 所以轉化為子結點 也就是深度大的結點即可
當查詢 x y 詢問的時候
一開始的想法:
比較x y 的深度 深度小的 轉化為其兒子 然後進行查詢
但是x和y的深度相同的時候 會出現問題 進一步發現 深度不同也會出錯
改進:標記跳到一條重鏈時的交叉結點 也就是最後乙個 x=fa[top[x]]
思路應該沒問題 但是很難維護最大最小值。。。
正解!!!!!
只要最後一次查詢的時候(也就是跳出while後) 改為 query(id[x]+1,id[y],1,n,1) 即可
這樣就會直接跳過 第二個思路那個標記點
新學會了一種維護 區間取反線段樹
#includeusingview codenamespace
std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ri(n) scanf("%d",&(n))
#define rii(n,m) scanf("%d%d",&n,&m)
#define riii(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define rs(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define rep(i,n) for(int i=0;i
#define clr(a,v) memset(a,v,sizeof a)
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
/////////////////////////////////
/#define inf 0x3f3f3f3f3f3f3f3f
const
int n=2e5+5
;ll minn[n
<<2],maxx[n<<2],t[n<<2],col[n<<2
],w[n],node[n];
int dep[n],top[n],fa[n],cnt,head[n],pos,siz[n],son[n],id[n],s[n][4],a,b,n,m;string
ss;void up(int
pos)
void down(int
pos)
}void build(int l,int r,int
pos)
int m=(l+r)>>1
; build(lson);build(rson);
up(pos);
}void upfan(int l,int r,int l,int r,int
pos)
down(pos);
int m=(l+r)>>1
;
if(l<=m)upfan(l,r,lson);
if(r>m)upfan(l,r,rson);
up(pos);
}void upnode(int x,int v,int l,int r,int
pos)
down(pos);
int m=(l+r)>>1
;
if(x<=m)upnode(x,v,lson);else
upnode(x,v,rson);
up(pos);
}ll qmax(
int l,int r,int l,int r,int
pos)
ll qmin(
int l,int r,int l,int r,int
pos)
ll qsum(
int l,int r,int l,int r,int
pos)
struct
edge
edge[n];
void add(int a,intb);
head[a]=pos;
}void dfs1(int x,int f,int
deep)
}void dfs2(int x,int
topf)
}ll upfan(
int x,int
y)
if(dep[x]>dep[y])swap(x,y);
upfan(id[x]+1,id[y],1,n,1);}
ll qsum(
int x,int
y)
if(dep[x]>dep[y])swap(x,y);
ans+=qsum(id[x]+1,id[y],1,n,1
);
return
ans;
}ll qmin(
int x,int
y)
if(dep[x]>dep[y])swap(x,y);
ans=min(ans,qmin(id[x]+1,id[y],1,n,1
));
return
ans;
}ll qmax(
int x,int
y)
if(dep[x]>dep[y])swap(x,y);
ans=max(ans,qmax(id[x]+1,id[y],1,n,1
));}
intmain()
dfs1(
1,0,1
); rep(i,
1,n-1
)
dfs2(
1,1);build(1,n,1
);ri(m);
while(m--)
if(ss=="c"
)
if(ss=="
sum")
if(ss=="
max")
if(ss=="
min")
}return0;
}
P1505 國家集訓隊 旅遊
題目鏈結 這道題其實還是比較好想的,同樣是邊權問題。我們需要維護最大值,最小值,和。最坑的地方就是路徑上的所有數變相反數,其實這個就是把區間和 1,區間最大 1,區間最小 1,最後pushdown的時候將取反標記 1,接下來一系列都是常規操作。而這裡還要記住,單點修改時也要下傳lazy標記。而我在跳...
題解 P1505 國家集訓隊 旅遊
這篇題解主要講 實現,思路可能需要照著 理解,請慎重閱讀 兩張掛了,重新傳了一遍。最後 寫出來3.5kb,不到150行,相對來說還是挺短的.給定一棵 n 個節點的樹,邊帶權,編號 0 sim n 1 需要支援五種操作 保證任意時刻所有邊的權值都在 1000,1000 內。前置知識 樹鏈剖分。主要講 ...
洛谷 P1505 國家集訓隊 旅遊
洛谷傳送門 ray 樂忠於旅遊,這次他來到了 t 城。t 城是乙個水上城市,一共有 nn 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說,t 城中只有 n 1n 1 座橋。ray 發現,有些橋上可以看到美麗的景色,讓人...