1. 程式人生 > >【SDOI 2011】染色

【SDOI 2011】染色

【題目】

傳送門

題目描述:

給定一棵有 n n 個節點的無根樹和 m m 個操作,操作有 2

2 類:

  1. 將節點 a a 到節點 b b 路徑上所有點都染成顏色 c
    c
  2. 詢問節點 a a 到節點 b b 路徑上的顏色段數量(連續相同顏色被認為是同一段),如
    112221 “112221”
    3 3 段組成: 11 “11” 222 “222” 1 “1”

請你寫一個程式依次完成這 m m 個操作。

輸入格式:

第一行包含 2 2 個整數 n n m m ,分別表示節點數和運算元;

第二行包含 n n 個正整數表示 n n 個節點的初始顏色;

下面 n 1 n-1 行每行包含兩個整數 x x y y ,表示 x x y y 之間有一條無向邊。

下面 m m 行每行描述一個操作:

C    a    b    c “C \;a\; b \;c” 表示這是一個染色操作,把節點 a a 到節點 b b 路徑上所有點(包括 a a b b )都染成顏色 c c

Q    a    b “Q \; a \; b” 表示這是一個詢問操作,詢問節點 a a 到節點 b b (包括 a a b b )路徑上的顏色段數量。

輸出格式:

對於每個詢問操作,輸出一行答案。

樣例資料:

輸入
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5

輸出
3
1
2

備註:

【資料範圍】
在這裡插入圖片描述
對於測試點 7 7 8 8 9 9 10 10 ,樹是這樣生成的:

隨機生成一個 1 1 n n 的排列 p p ,設 p 1 p_1 為根。對於 2 i n 2≤i≤n p i p_i 的父親為 Prandom(1,i-1),其中 Prandom(a,b) 以相等的概率返回 { x Z a x b } \{x∈Z|a≤x≤b\} 中的一個元素,然後將所有邊打亂順序後作為輸入提供給你的程式。

【友情提示】

不允許使用編譯開關改變棧空間大小,請選手儘量不要使用遞迴,以避免堆疊溢位。


【分析】

先講一下這道題如果不是在樹上操作,而是在序列上(也就是鏈的情況)該怎麼做

那麼,操作 1 1 就是普通的區間修改,套線段樹板子就行,難點是操作 2 2

對於每個線段樹的節點,記錄三個值:L 是序列最左邊的顏色,R 是序列最右邊的顏色,num 是這個區間的顏色段數量

假設 x 是當前節點,lc(x)x 的左區間,rc(x)x 的右區間

那麼顯然,若 R[lc(x)]=L[rc(x)],則 num[x]=num[lc(x)]+num[rc(x)]-1;否則 num[x]=num[lc(x)]+num[rc(x)]

知道了這個之後,在序列上的問題就迎刃而解了

現在把問題轉移到樹上來,其實也是差不多的思想,可以先用樹剖把樹劃成鏈,對鏈建線段樹,注意一點細節就可以了


【程式碼】

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100005
using namespace std;
int n,m,t,tot;
int first[N],v[N<<1],nxt[N<<1];
int a[N],fa[N],dep[N],idx[N],son[N],top[N],pos[N],Size[N];
struct Tree
{
	int L,R,num,mark;
	#define L(x) Seg[x].L
	#define R(x) Seg[x].R
	#define num(x) Seg[x].num
	#define mark(x) Seg[x].mark
}Seg[N<<2];
void add(int x,int y)
{
	t++;
	nxt[t]=first[x];
	first[x]=t;
	v[t]=y;
}
void dfs1(int x)
{
	int i,k;
	Size[x]=1,son[x]=0;
	for(i=first[x];i;i=nxt[i])
	{
		k=v[i];
		if(k==fa[x])  continue;
		fa[k]=x,dep[k]=dep[x]+1;
		dfs1(k),Size[x]+=Size[k];
		if(Size[k]>Size[son[x]])  son[x]=k;
	}
}
void dfs2(int x,int tp)
{
	int i,k;
	top[x]=tp,pos[x]=++tot,idx[tot]=x;
	if(son[x])  dfs2(son[x],tp);
	for(i=first[x];i;i=nxt[i])
	{
		k=v[i];
		if(k!=son[x]&&k!=fa[x])
		  dfs2(k,k);
	}
}
Tree pushup(Tree left,Tree right)
{
	Tree now;
	now.mark=0;
	now.L=left.L,now.R=right.R;
	now.num=left.num+right.num;
	if(left.R==right.L)  now.num--;
	return now;
}
void build(int root,int l,int r)
{
	if(l==r)
	{
		num(root)=1;
		L(root)=R(root)=a[idx[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(root<<1,l,mid);
	build(root<<1|1,mid+1,r);
	Seg[root]=pushup(Seg[root<<1],Seg[root<<1|1]);
}
void pushdown(int root)
{
	if(!mark(root))  return;
	L(root<<1)=R(root<<1)=mark(root<<1)=mark(root);
	L(root<<1|1)=R(root<<1|1)=mark(root<<1|1)=mark(root);
	num(root<<1)=num(root<<1|1)=1,mark(root)=0;
}
Tree query(int root,int l,int r,int x,int y)
{
	if(l>=x&&r<=y)
	  return Seg[root];
	int mid=(l+r)>>1;pushdown(root);
	if(y<=mid)  return query(root<<1,l,mid,x,y);
	if(x>mid)  return query(root<<1|1,mid+1,r,x,y);
	return pushup(query(root<<1,l,mid,x,y),query(root<<1|1,mid+1,r,x,y));
}
int ask(int x,int y)
{
	int ans=0,xx=0,yy=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y),swap(xx,yy);
		Tree res=query(1,1,n,pos[top[x]],pos[x]);ans+=res.num;
		if(xx==res.R)  ans--;  xx=res.L;
		x=fa[top[x]];
	}
	if(dep[x]>dep[y])swap(x,y),swap(xx,yy);
	Tree res=query(1,1,n,pos[x],pos[y]);ans+=res.num;
	if(xx==res.L)ans--;  if(yy==res.R)ans--;
	return ans;
}
void modify(int root,int l,int r,int x,int y,int k)
{
	if(l>=x&&r<=y)
	{
		num(root)=1;
		L(root)=R(root)=mark(root)=k;
		return;
	}
	int mid=(l+r)>>1;pushdown(root);
	if(x<=mid)  modify(root<<1,l
            
           

相關推薦

SDOI 2011染色

【題目】 傳送門 題目描述: 給定一棵有 n n n 個節點的無根樹和

枚舉SDOI 2011bzoj 2241打地鼠

desc 其它 規模 遊戲 pos 內部 ++ ack 至少 2241: [SDOI2011]打地鼠 Time Limit: 10 Sec Memory Limi

bzoj 2326HNOI 2011數學作業

alt cstring div ring ima void bzoj log 作業 題解:   矩陣裸體。    1 #include<cstdio> 2 #include<cstring> 3 #include<cma

NOIP 2011 Mayan遊戲

() tps maya mem 深度 may rem can remove 【題目鏈接】 https://www.luogu.org/problemnew/show/P1312 【算法】 深度優先搜索 【代碼】

SDOI 2016 排列計數

include bits span 因此 遞推公式 tar printf for 遞推 【題目鏈接】 https://www.lydsy.com/JudgeOnline/problem.php?id=4517 【算法】 有m個數在

BZOJ 1922SDOI 2010大陸爭霸(有限制的最短路)

(誰告訴我這是個分層最短路來著的???) 進入一個城市必須要這個城市所有結界都打破才能進 那我們可以邊炸邊走 也就是說 我們可以維護d1陣列:走到的時間(結界可能沒炸完) d2陣列:可進入的時間(結界都被炸完了) d陣列:真實的到達時間 容易發現d[i]=max(d1[i],d2[2]) 那我們就用dijks

BZOJ 2600IOI 2011ricehub(貪心+中位數)

拿到這道題一開始有兩個naive的想法 想法1:對於每個位置 向右擴充套件 直到不能取了為之 但是又覺得複雜度不對就放棄了...... 想法2:離散化座標 二分倉庫的位置 每次往左右兩邊數量較多的一邊靠(這是什麼口胡玩意兒???) 正解: 事實證明我是被ioi2011嚇到了 其實就是想法1加了一丟丟東西 維護

BZOJ2395Balkan 2011Timeismoney 最小乘積生成樹

imei 處理 最小乘積 一個 答案 轉化 每一個 兩個 。。 兩個屬性 考慮化成二維平面的點 每一個方案對應二維平面上的一個點(t,c) 答案一定在下凸殼上 先找到t,c的最小生成樹點A,B這兩者一定在凸包上 連線AB,找下面距離AB最遠點C 即CA CB叉積最小(註意帶

BZOJP2348Baltic 2011Plagiarism二分

水題不解釋 Code: #include<bits/stdc++.h> using namespace std; const int maxn=1e5+5; int a[maxn]; i

BZOJ 4816SDOI 2017數字表格

考慮到gcd(i,j)的這個形式是一個常見的莫比烏斯反演,嘗試建構函式。 1、列舉gcd,轉化為ans=∏nd=1f(d)h(d),其中h(d)=∑ni=1∑mj=1[gcd(i,j)==d]; 2、h(d)是莫比烏斯反演的模板題,直接上結論:h(d)=∑⌊

zoj 1610 Count the Colors 區間覆蓋 求染色

ble article 之前 n) 讓我 family define first main Count the Colors Time Limit: 2 Seconds Memory Limit: 65536 KB Painting so

bzoj 2303Apio2011方格染色

spa 有關 ... family target blog 思路 getchar() std 題目: http://www.lydsy.com/JudgeOnline/problem.php?id=2303 題解:   很神奇的思路,膜一發大佬http://www.cnbl

hihocoder 16512017-12-3 小球染色

需要 esp 輸出 space src return es2017 只需要 mil 時間限制:10000ms 單點時限:1000ms 內存限制:256MB 描述 小Ho面前有N個小球排成了一排。每個小球可以被染成M種顏色之一。 為了增強視覺效果,小Ho希

[SDOI 2011]染色

scrip 1+n lag esc lex include work flag lowbit Description 題庫鏈接 給定一棵有 \(n\) 個節點的無根樹和 \(m\) 個操作,操作有 \(2\) 類: 將節點 \(a\) 到節點 \(b\) 路徑上所有點都染

HRBUST 2011簡單dp

print 需要 CP down urn oid mes spa std 題意:N位士兵站成一排,長官要請其中的(N-K)位出列,使得剩下的K位士兵排成一等隊形。一等隊形是指這樣的一種隊形:設K位士兵從左到右依次編號為1,2…,K,他們的身高分別為T1,T2,…,TK, 則

51Nod1824 染色遊戲 Lucas定理FMT位運算

turn art 位運算 sizeof data color define stdin 無法 我的FMT是在VFleaKing的論文中學到的。51Nod的評測機好惡心。 題目分析: 題目很明顯是要你求一個類似卷積的式子。但是我們可以註意到前面具有組合數,如果拆成階乘會很

BZOJ2698染色

發現 我們 ont 方案 -s nbsp bzoj bsp color 題解: 首先比較顯然的是查詢每個點被覆蓋的概率,算完之後概率m次方 既然是計數題 考慮容斥 我們會發現這樣是求n長度的區間能存多少種 我們考慮直接遞推 從n到n+1 多的方案數一定要覆蓋n+

BZOJ 2120國家集訓隊 2011數顏色(莫隊)

修改 畫筆 out query ans urn 什麽 print ++z 題目描述 墨墨購買了一套N支彩色畫筆(其中有些顏色可能相同),擺成一排,你需要回答墨墨的提問。墨墨會向你發布如下指令: 1、 Q L R代表詢問你從第L支畫筆到第R支畫筆中共有幾種不同顏色的畫筆。

Tsinsen A1039bzoj2638黑白染色 (BFS樹)

efi span clu mat 黑白 cin pan ref clas Descroption 原題鏈接 你有一個\(n*m\)的矩形,一開始所有格子都是白色,然後給出一個目標狀態的矩形,有的地方是白色,有的地方是黑色,你每次可以選擇一個連通塊(四連通塊,且不要求顏色一樣

poj 1286 Necklace of Beads具有對稱性的計數polya計數項鍊染色方案數

【連結】 http://poj.org/problem?id=1286 【題意】 n個珠子串成一個圓,用三種顏色去塗色。問一共有多少種不同的塗色方法(翻轉,旋轉相同) 翻轉:如果n是奇數,則存在n中置換,每種置換包含n/2+1種迴圈(即輪換)。     &nb