樹上莫隊 樹剖 神奇的姿勢 嘿嘿嘿嘿的 zy

2021-07-28 13:34:58 字數 4388 閱讀 8378

題目描述

hjwjssb成年了,父母覺得他是時候去找乙個喜歡的人。他遇到了室友hao,在和hao一起同居的兩年,hjwjssb不知不覺中對hao產生了一點好感。後來hjwjssb換了乙個公司,遇到了同事ciewai。ciewai對他很好,經常加班陪他,等他一起回家,hjwjssb接觸ciewai這麼久後,也感覺ciewai對自己有一些愛慕,可是他又有點放不下hao,於是他找到了他曾經的王者,問他怎麼辦,王者用他智慧型的大腦說為了你的後代考慮,你應該給他們出一道題,若誰先做出這道題,誰的智商就更高一些,這樣你就能更好的選擇……

於是hjwjssb拿著王者出的題給了ciewai和hao,然而ciewai很蠢,hao很聰明,但是ciewai卻不想認輸,於是ciewai找到聰明的你,求你來幫幫ciewai,讓ciewai獲得真愛……

王者出的題目是這樣的:

給一顆n

個點的樹,每乙個點有乙個顏色,然後維護幾個操作。

操作 1:t=

1時,將

x 點的顏色修改為y;

操作 2:t=

2 時,詢問

x 到

y路徑上有多少個不同的顏色段;

操作 3:t=

3 時,詢問

x 到

y路徑上的出現次數最多的顏色的出現次數。

輸入
第一行兩個數n,

q ,分別表示樹的點數和操作個數。

第二行n

個數,分別表示每個點的顏色。 第3

行到第n+1

行每行兩個數x,

y 表示

x 到

y有一條無向邊。 第n

+2行到第n+

q+1 行每行

3 個數,t,

x,y。

輸出
輸出的行數為詢問個數,每一行輸出當前詢問的答案。

樣例輸入
5 4

2 3 1 3 1

1 21 3

2 42 5

2 4 3

3 4 5

1 3 2

2 3 4

樣例輸出
3

22

資料範圍
對於20%的資料:1≤

n≤100,1≤

q≤100 ;

另有15%的資料:樹是一條鏈,只有操作

1 和操作2;

另有15%的資料:只有操作

1 和操作2;

另有15%的資料:樹是一條鏈,只有操作

1 和操作3;

另有15%的資料:只有操作

1 和操作3;

對於100%的資料:1≤

n≤100000,1

≤q≤100000,0

≤顏色大

小≤100000

後記
最後在你的幫助下ciewai贏了hao,可是hjwjssb還是十分猶豫,於是他去問了他曾經的王者,王者告訴他說既然你覺得很難選擇,那就不如都選擇!!!

於是hjwjssb和ciewai,還有hao幸福快樂的生活在了一起……

orz禎哥,祝禎哥早日得到妹子的認可,noi進隊!!!

首先吐槽一下題面……排版標點符號什麼的不說了……到最後為什麼還得到妹子認可啊……怎麼都愛玩這種大家幸福快樂生活在一起的結局,之前還做過一套什麼現充小司姬老司機的題……

嗯說這道題。

這不就乙個送分題麼……操作2就是個樹剖啊同sdoi染色,操作3就是個樹上莫隊啊……

等等,這題莫隊怎麼做,區間眾數……

莫隊這東西需要每次操作o(

1)才是o(

nn‾√

) 的,一開始只想到線段樹,看時限有12s,以為帶個

log 之前

出現次數

−1,所以就很愉快的o(

1)轉移啦。不過要是求眾數呢……不太知道,有神犇會歡迎指導。

%%%各種85分神犇

%%%commonc最後30sac

**自我感覺還是能看的。不用注釋了吧明眼人都看得懂。這種思路很清晰的題一般**寫的都還好……像什麼重建計畫……哦呵呵。

#include 

#include

#include

#include

using

namespace

std;

struct edge

edge(){}

}pool[200010], *g[100010];

struct queqs[100010];

int n, q, nt, arr[100010];

inline

int rd()

namespace t2qs[100010];

struct rec

rec()

rec rev()

};struct node

node(){}

}pool[200010], *root;

int nt, nw, nq, fa[100010], son[100010], siz[100010], dep[100010], top[100010], w[100010], to[100010];

rec merge(rec a, rec b)

void build(node *p)

p->lch=&(pool[nt++]=node(p->l, p->m)); build(p->lch);

p->rch=&(pool[nt++]=node(p->m, p->r)); build(p->rch);

p->rr=merge(p->lch->rr, p->rch->rr);

}void dfs1(int p)

}void dfs2(int p, int t)

}void init()

int lca(int u, int v)

if(km) mseg(p->lch, k, v);

else mseg(p->rch, k, v);

p->rr=merge(p->lch->rr, p->rch->rr);

}rec qseg(node *p, int l, int r)

int query(int u, int v)

if(dep[u]<=dep[v])

ll=merge(ll, qseg(root, w[u], w[v]+1));

else

ll=merge(ll, qseg(root, w[v], w[u]+1).rev());

return merge(ll, rr).cnt;

}void go()

}}namespace t3qs[100010];

struct modms[100010];

int nq, seq[200010], h, op[100010], ed[100010], bel[200010], bk;

int cnt[100010], cntt[100010], now;

bool v[100010];

void dfs(int p, int f)

seq[ed[p]=h++]=p;

}void pq()

else

if(p[i].opt==2) continue;

else

}for(int i=x;i>0;i--)

arr[ms[i].k]=ms[i].p;

}void init()

void del(int p)

void tog(int p)

bool cmpp(que a, que b)

while(x>qs[i].x)

while(lwhile(l>qs[i].l) tog(seq[--l]);

while(rwhile(r>qs[i].r) tog(seq[r--]);

tog(qs[i].lca); qs[i].ans=now;

tog(qs[i].lca);

}sort(qs, qs+nq, cmpi);

}}int main()

for(int i=0;iint pt1=0, pt2=0;

while(pt1if(t2::qs[pt1].idprintf("%d\n", t2::qs[pt1++].ans);

else

printf("%d\n", t3::qs[pt2++].ans);

while(pt1printf("%d\n", t2::qs[pt1++].ans);

while(pt2printf("%d\n", t3::qs[pt2++].ans);

return

0;}

typecho怎麼莫名吞文章啊……有點方。發在cdsn當備份好了。大概是一定要搬家的。

BZOJ 4129 樹上帶修莫隊 線段樹

思路 可以先做做bzoj3585 是序列上的mex 考慮莫隊的轉移 如果當前數字出現過 線段樹上把它置成1 對於詢問 二分ans 線段樹上查 0到ans的和 是不是ans 1 本題就是把它搞到了序列上 帶了個修改 麻煩一點 本質上是一樣的 by siriusren include include i...

BZOJ 4129 樹上帶修莫隊 線段樹

思路 可以先做做bzoj3585 是序列上的mex 考慮莫隊的轉移 如果當前數字出現過 線段樹上把它置成1 對於詢問 二分ans 線段樹上查 0到ans的和 是不是ans 1 本題就是把它搞到了序列上 帶了個修改 麻煩一點 本質上是一樣的 by siriusren include include i...

SPOJ COT2 樹上的莫隊演算法,樹上區間查詢

題意 n個節點形成的一棵樹。每個節點有乙個值。m次查詢,求出 u,v 路徑上出現了多少個不同的數。樹上的莫隊演算法,同樣將樹分成siz sqrt n 塊,然後離線操作。先對樹dfs一遍,每當子樹節點個數num siz,就將這num個分成一塊。讀取所有的查詢按左端點所在塊排序。重點在於怎麼進行區間轉移...