題目描述
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個分成一塊。讀取所有的查詢按左端點所在塊排序。重點在於怎麼進行區間轉移...