【SDOI 2011】染色
【題目】
題目描述:
給定一棵有 個節點的無根樹和 個操作,操作有 類:
- 將節點 到節點 路徑上所有點都染成顏色 ;
- 詢問節點 到節點 路徑上的顏色段數量(連續相同顏色被認為是同一段),如 由 段組成: 、 和 。
請你寫一個程式依次完成這 個操作。
輸入格式:
第一行包含 個整數 和 ,分別表示節點數和運算元;
第二行包含 個正整數表示 個節點的初始顏色;
下面 行每行包含兩個整數 和 ,表示 和 之間有一條無向邊。
下面 行每行描述一個操作:
表示這是一個染色操作,把節點 到節點 路徑上所有點(包括 和 )都染成顏色 ;
表示這是一個詢問操作,詢問節點 到節點 (包括 和 )路徑上的顏色段數量。
輸出格式:
對於每個詢問操作,輸出一行答案。
樣例資料:
輸入
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
備註:
【資料範圍】
對於測試點
、
、
、
,樹是這樣生成的:
隨機生成一個 ~ 的排列 ,設 為根。對於 , 的父親為 Prandom(1,i-1),其中 Prandom(a,b) 以相等的概率返回 中的一個元素,然後將所有邊打亂順序後作為輸入提供給你的程式。
【友情提示】
不允許使用編譯開關改變棧空間大小,請選手儘量不要使用遞迴,以避免堆疊溢位。
【分析】
先講一下這道題如果不是在樹上操作,而是在序列上(也就是鏈的情況)該怎麼做
那麼,操作 就是普通的區間修改,套線段樹板子就行,難點是操作
對於每個線段樹的節點,記錄三個值: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 2011】【bzoj 2241】打地鼠
desc 其它 規模 遊戲 pos 內部 ++ ack 至少
2241: [SDOI2011]打地鼠
Time Limit: 10 Sec Memory Limi
【bzoj 2326】【HNOI 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 1922】【SDOI 2010】大陸爭霸(有限制的最短路)
(誰告訴我這是個分層最短路來著的???)
進入一個城市必須要這個城市所有結界都打破才能進
那我們可以邊炸邊走 也就是說 我們可以維護d1陣列:走到的時間(結界可能沒炸完) d2陣列:可進入的時間(結界都被炸完了) d陣列:真實的到達時間
容易發現d[i]=max(d1[i],d2[2])
那我們就用dijks
【BZOJ 2600】【IOI 2011】ricehub(貪心+中位數)
拿到這道題一開始有兩個naive的想法
想法1:對於每個位置 向右擴充套件 直到不能取了為之 但是又覺得複雜度不對就放棄了......
想法2:離散化座標 二分倉庫的位置 每次往左右兩邊數量較多的一邊靠(這是什麼口胡玩意兒???)
正解:
事實證明我是被ioi2011嚇到了
其實就是想法1加了一丟丟東西 維護
【BZOJ2395】【Balkan 2011】Timeismoney 最小乘積生成樹
imei 處理 最小乘積 一個 答案 轉化 每一個 兩個 。。 兩個屬性
考慮化成二維平面的點
每一個方案對應二維平面上的一個點(t,c)
答案一定在下凸殼上
先找到t,c的最小生成樹點A,B這兩者一定在凸包上
連線AB,找下面距離AB最遠點C
即CA CB叉積最小(註意帶
【BZOJ】【P2348】【Baltic 2011】【Plagiarism】【二分】
水題不解釋
Code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
i
【BZOJ 4816】【SDOI 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 2303】【Apio2011】方格染色
spa 有關 ... family target blog 思路 getchar() std 題目:
http://www.lydsy.com/JudgeOnline/problem.php?id=2303
題解:
很神奇的思路,膜一發大佬http://www.cnbl
【hihocoder 1651】2017-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 A1039】【bzoj2638】黑白染色 (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