bzoj3307 雨天的尾巴

2021-07-09 20:44:43 字數 2964 閱讀 3316

time limit: 10 sec  

memory limit: 128 mb

submit: 258  

solved: 121 [

submit][

status][

discuss]

n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y

對於x到y的路徑上(含x,y)每個點發一袋z型別的物品。完成

所有發放後,每個點存放最多的是哪種物品。

第一行數字n,m

接下來n-1行,每行兩個數字a,b,表示a與b間有一條邊

再接下來m行,每行三個數字x,y,z.如題

輸出有n行

每i行的數字表示第i個點存放最多的物品是哪一種,如果有

多種物品的數量一樣,輸出編號最小的。如果某個點沒有物品

則輸出0

20 50

8 610 6

18 6

20 10

7 20

2 18

19 8

1 614 20

16 10

13 19

3 14

17 18

11 19

4 11

15 14

5 18

9 10

12 15

11 14 87

12 1 87

14 3 84

17 2 36

6 5 93

17 6 87

10 14 93

5 16 78

6 15 93

15 5 16

11 8 50

17 19 50

5 4 87

15 20 78

1 17 50

20 13 87

7 15 22

16 11 94

19 8 87

18 3 93

13 13 87

2 1 87

2 6 22

5 20 84

10 12 93

18 12 87

16 10 93

8 17 93

14 7 36

7 4 22

5 9 87

13 10 16

20 11 50

9 16 84

10 17 16

19 6 87

12 2 36

20 9 94

9 2 84

14 1 94

5 5 94

8 17 16

12 8 36

20 17 78

12 18 50

16 8 94

2 19 36

10 18 36

14 19 50

4 12 50

8736

8422

8787

2250

8487

5036

8793

3694

1687

5050

1<=n,m<=100000

1<=a,b,x,y<=n

1<=z<=10^9

資料結構好題!

首先我們考慮如果是區間上怎麼處理。對於乙個區間[l,r]每個點放乙個z物品,只需要在l處打上z+1的標記,r+1處打上z-1的標記。最後o(n)將整個序列掃一遍,用線段樹維護每種物品的數量即可。

那麼轉化到樹上的鏈操作呢?用樹鏈剖分將鏈轉化為若干各區間,再對於每乙個區間分別打標記。

這道題re了很多次,對拍之後發現是樹剖寫錯了...qaq

#include#include#include#include#include#include#include#define f(i,j,n) for(int i=j;i<=n;i++)

#define d(i,j,n) for(int i=j;i>=n;i--)

#define ll long long

#define maxn 100005

#define maxm 2500005

using namespace std;

int n,m,x,y,z,cnt,tot;

int a[maxn],p[maxn],f[maxn],d[maxn],fa[maxn],sz[maxn];

int ans[maxn],son[maxn],head[maxn],belong[maxn];

struct edgee[maxn*2];

struct datag[maxm];

struct segt[maxn*4];

mapmp;

inline int read()

while (ch>='0'&&ch<='9')

return x*f;

}inline void add_edge(int x,int y)

;head[x]=cnt;

e[++cnt]=(edge);head[y]=cnt;

}inline void add_data(int pos,int x,int y)

;head[pos]=cnt;

}inline void dfs1(int x)

}inline void dfs2(int x,int chain)

inline bool cmp(int x,int y)

inline void add(int k,int pos,int x)

int mid=(t[k].l+t[k].r)>>1;

if (pos<=mid) add(k<<1,pos,x);

else add(k<<1|1,pos,x);

pushup(k);

}int main()

build(1,1,m);

f(i,1,n)

f(i,1,n) printf("%d\n",a[ans[i]]);

}

BZOJ3307 雨天的尾巴

線段樹合併 在鏈的兩端x,y各打上1個z的加標記,在lca x,y 打上1個z的減標記,在fa lca x,y 打上1個z的減標記,每個節點和所有孩子的線段樹合併,查詢時線段樹上二分 code include include include include include include inclu...

BZOJ3307 雨天的尾巴

bzoj許可權題 良心洛谷 這道題目的花呢,本來想縮先樹剖 可能需要長鏈剖分?再搞乙個標記永久化,然後最後合併答案,不過可能會卡空間。時間複雜度呢是o nlog 2n o n log2 n 然後boshi表示 為什麼不差分然後再自底向上合併線段樹呢 於是就做到了o nlog n o n logn 好...

BZOJ3307 雨天的尾巴

n個點,形成乙個樹狀結構。有m次發放,每次選擇兩個點x,y 對於x到y的路徑上 含x,y 每個點發一袋z型別的物品。完成 所有發放後,每個點存放最多的是哪種物品。第一行數字n,m 接下來n 1行,每行兩個數字a,b,表示a與b間有一條邊 再接下來m行,每行三個數字x,y,z.如題 輸出有n行 每i行...