清華冬令營2018模擬 送你一棵聖誕樹

2021-08-14 10:55:05 字數 1839 閱讀 3608

對於每個詢問輸出一行乙個整數, 表示答案.

5 5 0

5 5 2 5 5

5 1

2 5

4 2

3 5

1 2 2 3

2 5 1

1 1 1 5

2 3 2

1 3 1 5

0 3

15 5 1

4 1 1 5 4

5 1

3 5

2 3

4 3

2 5 4

2 2 2

1 3 1 5

2 1 2

1 1 2 73 1

這題雖說是資料結構題,但是不很經典

比較經典的做法就是按照dfs序線段樹或者樹鏈剖分,這是比較好想的

但是這題如果這麼想就容易想歪

首先對於每個顏色,開個set記錄這個顏色的點的dfs序,也就是排好序了的

對乙個顏色,每個點自己位置+1,set中dfs序相鄰位置的lca-1,這樣統計貢獻時,直接子樹權值和就行(畫張圖理解一下)

多個顏色就開樹狀陣列套線段樹就行了

#include

#include

#include

#include

#define fo(i,a,b) for(int i=a;i<=b;i++)

#define fd(i,a,b) for(int i=a;i>=b;i--)

#define n 101000

#define lowbit(x) (x&(-x))

using namespace std;

int a[n],last[n],next[n*2],to[n*2],n,q,zx,f[n][17],bz[n],tot=0,t[n*2],ans,dfn[n],low[n],deep[n],fdfn[n];

struct nodeg[n*200];

set c[n];

typedef set :: iterator it;

void putin(int

x,int

y)void dg(int

x) low[x]=tot;

}int lca(int

x,int

y)void change(int v,int i,int j,int

x,int

y) int

m=(i+j)/2;

if(x

<=m) g[v].l=g[v].l==0?++tot:g[v].l,change(g[v].l,i,m,x,y);

else g[v].r=g[v].r==0?++tot:g[v].r,change(g[v].r,m+1,j,x,y);

g[v].sz=g[g[v].l].sz+g[g[v].r].sz;

}int find(int v,int i,int j,int

x,int

y)void ins(int

x,int

y,int z)

int get(int

x,int l,int r)

int main()

tot=0;deep[1]=1;dg(1);

fo(j,1,16) fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1];

fo(i,1,n) t[i]=i,c[a[i]].insert(dfn[i]),c[i].insert(0),c[i].insert(n+1);

tot=n;

fo(i,1,n)

}while(q--)

if(tag==2)

}}

5507 清華冬令營2018模擬 取石子

直接說做法了,挺好理解的。欽定a b a le b a b。設r x mod a b r x mod a b r xmod a b 分四種情況討論 r 0,a 1 r in 0,a 1 r 0,a 1 這個情況沒有意義。r a,b 1 r in a,b 1 r a,b 1 這個情況下,a aa能多走...

清華2019冬令營模擬12 8 視野

計算幾何弱渣果然就是一點感覺也沒有。首先考慮不刪怎麼做?肯定要把點給離散,那麼現在對於每一小段,要求出是哪條線段最近?按乙個順序掃過去,每一條線段打乙個加入和刪除的標記。由於線段互不相交,所以線段順序不會隨著小段的移動而改變。因此,我們可以用乙個set去維護插入刪除,比較遠近時,就求交,判斷誰近。那...

位元組跳動冬令營2018

給定一棵有根樹,邊有邊權,兩個人輪流操作,每次可以把一條邊的權值減少一,權值變為 0 表示把子樹砍掉,問先手第一輪操作哪些邊使得自己必勝。n 1 06 n leq 10 6 n 10 6之前的部落格,發現這道題本質上是圖的刪邊遊戲。把環縮掉,就變成了樹上刪邊遊戲了。結論是 葉子的 sg 為 0,非葉...