BZOJ2157旅遊 樹鏈剖分 線段樹

2022-05-08 03:39:08 字數 3459 閱讀 3907

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 行,每行描述了乙個操作,操作有如下五種形式: c i w,表示ray 對於經過第i 座橋的愉悅度變成了w。 n u v,表示ray 對於經過景點u 到v 的路徑上的每一座橋的愉悅度都變成原來的相反數。 sum u v,表示詢問從景點u 到v 所獲得的總愉悅度。 max u v,表示詢問從景點u 到v 的路徑上的所有橋中某一座橋所提供的最大愉悅度。 min u v,表示詢問從景點u 到v 的路徑上的所有橋中某一座橋所提供的最小愉悅度。測試資料保證,任意時刻,ray 對於經過每一座橋的愉悅度的絕對值小於等於1000。

對於每乙個詢問(操作s、max 和min),輸出答案。

30 1 1

1 2 2

8sum 0 2

max 0 2

n 0 1

sum 0 2

min 0 2

c 1 3

sum 0 2

max 0 232

1-153

一共有10 個資料,對於第i (1 <= i <= 10) 個資料, n = m = i * 2000。

這道題思路很簡單,但碼量有點大啊。兩種修改,三種查詢,直接樹鏈剖分+線段樹就好了。但細節比較多,特別注意最大值和最小值初始值的設定。還有就是節點編號從0開始,因此要都+1.

#include#include#include#include#include#include#include#include#include#includeusing namespace std;

int n,m;

int tot;

int num;

int x,y,z;

char ch[7];

int s[20010];

int f[20010];

int d[20010];

int q[20010];

int v[20010];

int a[160010];

int to[40010];

int mx[160010];

int mn[160010];

int son[20010];

int top[20010];

int val[40010];

int sgn[40010];

int sum[160010];

int size[20010];

int head[20010];

int next[40010];

mapb;

void add(int x,int y,int z,int w)

void dfs(int x,int fa)}}

}void dfs2(int x,int tp)

for(int i=head[x];i;i=next[i])

}}void pushup(int rt)

void pushdown(int rt)

}void build(int rt,int l,int r)

int mid=(l+r)>>1;

build(rt<<1,l,mid);

build(rt<<1|1,mid+1,r);

pushup(rt);

}void updata(int rt,int l,int r,int k,int v)

pushdown(rt);

int mid=(l+r)>>1;

if(k<=mid)

else

pushup(rt);

}void change(int rt,int l,int r,int l,int r)

pushdown(rt);

int mid=(l+r)>>1;

if(l<=mid)

if(r>mid)

pushup(rt);

}int querymax(int rt,int l,int r,int l,int r)

pushdown(rt);

int mid=(l+r)>>1;

int res=-2147483647;

if(l<=mid)

if(r>mid)

return res;

}int querymin(int rt,int l,int r,int l,int r)

pushdown(rt);

int mid=(l+r)>>1;

int res=2147483647;

if(l<=mid)

if(r>mid)

return res;

}int querysum(int rt,int l,int r,int l,int r)

pushdown(rt);

int mid=(l+r)>>1;

int res=0;

if(l<=mid)

if(r>mid)

return res;

}void find(int x,int y)

change(1,1,n,s[son[x]],s[y]);

}}int askmax(int x,int y)

res=max(res,querymax(1,1,n,s[son[x]],s[y]));

}return res;

}int askmin(int x,int y)

res=min(res,querymin(1,1,n,s[son[x]],s[y]));

}return res;

}int asksum(int x,int y)

res+=querysum(1,1,n,s[son[x]],s[y]);

}return res;

}int main()

dfs(1,0);

dfs2(1,1);

build(1,1,n);

scanf("%d",&m);

for(int i=1;i<=m;i++)

else if(ch[0]=='n')

else if(ch[0]=='s')

else

else}}

}

bzoj2157 旅遊 樹鏈剖分 線段樹

題目描述 ray 樂忠於旅遊,這次他來到了t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說,t 城中只有n 1 座橋。ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有...

BZOJ2157 旅遊 樹鏈剖分 線段樹

在對樹中資料進行改動的時候需要很多pushdown 具體操作見 不然會wa,大概原因和線段樹區間修改需要很多pushup是一樣的。這個輕重鏈的方法特別好用,雖然第一次寫樹鏈剖分但是容易理解又有優秀複雜度的結構讓人情不自禁orz。後來發現很久以前學lca的時候就學了樹鏈剖分只不過忘了,mdzz 因為忘...

BZOJ 2157 旅遊 樹鏈剖分

ray 樂忠於旅遊,這次他來到了t 城。t 城是乙個水上城市,一共有 n 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,t 城的任意兩個景點之間有且只有一條路徑。換句話說,t 城中只有n 1 座橋。ray 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥...