P1505 國家集訓隊 旅遊

2022-05-01 14:03:08 字數 3751 閱讀 7355

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) 即可

這樣就會直接跳過 第二個思路那個標記點

新學會了一種維護 區間取反線段樹

#includeusing

namespace

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;

}

view code

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 發現,有些橋上可以看到美麗的景色,讓人...