「題目背景」
小奇在家中的花園漫步時,總是會思考一些奇怪的問題。
「問題描述」
小奇的花園有n個溫室,標號為1到n,溫室以及以及溫室間的雙向道路形成一棵樹。
每個溫室都種植著一種花,隨著季節的變換,溫室裡的花的種類也在不斷發生著變化。
小奇想知道從溫室x走到溫室y的路徑中(包括兩個端點),第t種花出現的次數。
「輸入格式」
第一行為兩個整數n,q,表示溫室的數目和操作的數目。
第二行有n個整數t1,t2…tn其中ti表示溫室i中的花的種類。
接下來n-1行,每個兩個整數x, y,表示溫室x和y之間有一條雙向道路。
接下來q行,表示q個操作,分別為以下兩種形式之一:
• c x t 表示在溫室x中的花的種類變為t。
• q x y t 表示詢問溫室x走到溫室y的路徑中(包括兩個端點),第t種花出現
的次數。
「輸出格式」
輸出q行,每行乙個正整數表示該次詢問答案。
「樣例輸入」
5 8「樣例輸出」10 20 30 40 50
1 21 3
3 43 5
q 2 5 10
c 2 21
q 3 4 21
c 6 22
q 1 7 28
c 5 20
q 2 5 20
q 2 0 9
120「樣例解釋」加密前的操作:31
q 2 5 10
c 3 20
q 2 5 20
c 4 20
q 3 5 30
c 5 20
q 2 5 20
q 1 3 10
「資料範圍」
對於30%的資料,有n <= 1000, q <= 2000。
對於50%的資料,有n <= 10000, q <= 20000。
對於100%的資料,有n <= 100000, q <= 200000,0 <= t < 2^31。
←小奇
下面的題解都是自己的話:
50%
考場上實在沒辦法ac拿50分也不吃虧。
100%
有乙個轉化很重要。
我們可以通過類似求樹上兩點路徑長度 dis=dep[x]+dep[y]-dep[lca]*2 的方法,用s[i]表示從根節點到此時的i點col顏色的出現次數。
所以每次在某個節點的某個顏色出現次數增加1時,它的整個子樹的每個節點的s[i]都會增加1,那麼從x到y某個顏色的出現次數顯然就變成 s[x]+s[y]-s[lca]*2+val[lca]了
那這樣題目要求的單點修改、區間查詢就被我們變成子樹修改、單點查詢了。子樹修改用dfs序來看其實也就是區間修改了,可以用線段樹解決。
但是顏色種類那麼多怎麼辦呢(而且數值還那麼大)?
可以用map來維護顏色編號,用動態開點線段樹的方式對每一種顏色維護一棵線段樹。
做本題是參考了黃學長hzwer的題解和程式,**可能有相似之處,但線段樹的操作絕對是我自己的風格。(求資瓷~)
1 #include2 #include3 #include4 #include5 #include6 #include78#define for(i,a,b)for(register int i=a;i<=b;++i)
9#define dwn(i,a,b)for(register int i=a;i>=b;--i)
10#define re register
11#define pn putchar('\n')
1213
using
namespace
std;
1415
const
int n=1e5+5,nr=1e7+5;16
int head[n],nxt[n*2],v[n*2],cnt=1;17
int f[n][21],dfx[n],did=0
,dep[n],sz[n];
18int rt[n*3],ls[nr],rs[nr],tag[nr],tr[nr],tid=0;19
int n,m,x,y,t[n*3],cid=0,t,q,ans=0
;20 mapmp;
21 inline void read(int &v)
27void write(int
x)32
void add(int ux,int
vx)38
39void dfs(int x,int
fa)50}51
52int lca(int x,int
y)57
if(x==y)return
x;58 dwn(b,20,0)if(f[x][b]!=-1&&f[y][b]!=-1&&f[x][b]!=f[y][b])
61return f[x][0
];62}63
6465
void pdown(int o,int l,int
r)73
74void ins(int &o,int l,int r,int lx,int rx,int
dt)80
pdown(o,l,r);
81int m=(l+r)>>1;82
if(lx<=m)ins(ls[o],l,m,lx,rx,dt);
83if(rx>m)ins(rs[o],m+1
,r,lx,rx,dt);84}
8586
int qry(int o,int l,int r,int
px)94
9596
intmain()
105 for(i,1,n-1
)109
110 memset(f,-1,sizeof
(f));
111 dfs(1,0
);112 for(b,1,20) for(i,1
,n)116
117 for(i,1
,n)122
123 for(i,1
,q)138
if(opt=='q'
)151
}152
fclose(stdin); fclose(stdout);
153return0;
154 }
Luogu U16325小奇的花園(樹鏈剖分)
題目鏈結 學了學動態開點的樹鏈剖分,其實跟動態開點的線段樹差不多啦 查詢的時候別ssbb地動態開點,如果沒這個點果斷返回0就行 只要注意花的種類能到intmax就行qwq!include include include include include include define mid l r 1...
JZOJ 省選模擬 夕張的改造 kaisou
description 提督們驚奇地發現,2019 年實裝的改造非常少。經調查,原來是改造廠的廠長於八日剋扣了其他艦娘改造的圖紙,並且在 2020 年的第乙個月利用這些圖紙進行了華麗的改造,一共有三種形態,於八日改二,於八日改二特,於八日改二丁,對空 對陸 對潛 開幕雷 五裝備格,無所不能。鎮守府雪...
BSOJ3392 省選模擬 樹上的詢問
bsoj3392 省選模擬 樹上的詢問 點分治。點分治入門題,首先這題可以直接做,也可以轉化成 小於等於 k 的減掉 小於等於 k 1 的 然後相減來做。兩者皆可。includeusing namespace std define ll long long define ull unsigned l...