2019北京集訓3 邏輯 樹剖 2 sat

2022-05-03 18:57:11 字數 1415 閱讀 9535

題目大意:有一顆有$m$個葉子節點的二叉樹。

對於葉子節點$i$,$x[i]=(a[i]\ xor\ v_)or(b[i]\ xor\ v_)$

對於非葉子節點$i$,$x[i]=x[sonl]\ and\ x[sonr]$。

上文的$or$和$xor$均為邏輯運算子。且v為乙個長度為$n$的布林陣列,需要你自己構造。

下面問:對於每個非葉子節點$i$,問是否存在乙個序列v,使得$x[i]=true$。

資料範圍:$n,m≤2\times 10^$

我們先來考慮下暴力應該怎麼做

我們直接暴力將以$i$為根的子樹內所有葉節點取出,轉換出對應的了邏輯表示式,然後根據2-sat那一套建圖,直接tarjan即可。

這麼搞,資料優秀的話(給你乙個毛毛蟲圖),你就會**

考慮一種不會**的做法:

我們對這棵樹跑一次樹剖,我們根據鏈長依次在鏈上進行二分,查詢出最接近根的,能夠構造出true的點。

然後冷靜分析一波,發現這個複雜度好像是$o(n\log^2\ n)$的,似乎問題不大。

可是問題在於這一題採用$o(n^2)$的做法可以直接艹過此題,我就並沒有去寫高階做法了qwq

1 #include2

#define m 500005

3using

namespace

std;45

int n,m,rt=0;6

int p[m]=,q[m]=,a[m]=,b[m]=,in[m]=;

78 vectorg[m];910

void

readdata()

17for(int i=m+1;i2;i++)

23for(int i=1;i2;i++)

24if(in[i]==0)25}

2627

struct edgee[m*2]=; int head[m]=,use=0;28

void add(int x,int y)

29int dfn[m]=,low[m]=,b[m]=,d[m]=,cnt=0,t=0; stacks;

30void dfs(int

x)while(u!=x);41}

42}4344 vectorlist;

45void findpoint(int

x)55

for(int i=0;i)

56findpoint(g[x][i]);57}

5859

bool check(int

x)70

for(int i=0;i)

76for(int i=0;i)

82return1;

83}8485

int ans[m]=;

86bool solve(int x,int

ok)92

93int

main()

2019北京集訓測試賽(十三) 函樹 虛樹

題目大意 給你一顆 n 個節點的樹,定義 d x,y 點 x 到點 y 最短路上經過的邊數。求 sum limits sum limits varphi i times j times d i,j 答案對998244353 取模。我們對這個式子做一些細微的處理,設最終的答案為 ans ans sum...

北京集訓D2T3 tvt

首先需要對兩條路徑求交,對給出的四個點的6個lca進行分類討論。易於發現路徑的交就是這六個lca裡面最深的兩個所形成的鏈。然後即可再分兩種情況進行討論。對於同向的路徑,我們可以求出到達交的起點的時間差,然後與鏈上的最長邊進行比較,如果大於說明可行。對於對向的路徑,如果能在時間差內走到交集上,同時不是...

2016北京集訓測試賽1 奇怪的樹 樹鏈剖分

對於操作1,不論選了哪個點為a,最後反轉顏色的點集都只有兩種型別 顯然啦 暴力解法 對每個操作3,從a向上直到根節點,每到乙個節點記錄 它父親的黑點數減去自己的黑點數 父親節點的編號。另外,還要記錄a子樹內的黑點。這種o n2 的做法肯定會爆,考慮優化。由於這是一棵靜態樹,考慮樹鏈剖分。需要記錄乙個...