Bzoj 2759 乙個動態樹好題

2021-07-25 16:33:27 字數 2591 閱讀 4660

有n個未知數x[1..n]和n個等式組成的同餘方程組:

x[i]=k[i]*x[p[i]]+b[i] mod 10007

其中,k[i],b[i],x[i]∈[0,10007)∩z

你要應付q個事務,每個是兩種情況之一:

一.詢問當前x[a]的解

a a無解輸出-1

x[a]有多解輸出-2

否則輸出x[a]

二.修改乙個等式

c a k[a] p[a] b[a] n

下面n行,每行三個整數k[i] p[i] b[i]

q下面q行,每行乙個事務,格式見題目描述

對每個詢問,輸出一行乙個整數。

對100%的資料,1≤n≤30000,0≤q≤100000,時限2秒,其中詢問事務約佔總數的80% 5

2 2 1

2 3 2

2 4 3

2 5 4

2 3 5

5a 1

a 2c 5 3 1 1

a 4a 5

4276

7141

4256

2126

分析:因為刪錯了邊被這題卡了整整一天,還是在看了題解的情況下,思路還是蠻神奇的,

可以看出原圖中每個聯通分量都是乙個環套樹,然後我們把環上一邊拆掉然後用動態樹維

護,因為是有向圖,所以這棵樹不能換根,我是在動態樹分類下找到這道題的,但是一直

想不出怎麼用動態樹維護這種東西,因為印象裡平衡樹都是通過updata合併兩個兒子的屬

性來更新自己的值,而這題很明顯邊是要從兒子指向父親的,這怎麼維護呢。。。

然後神奇的思路是,我們不需要對平衡樹中的每乙個點都去直接維護它的值,我們只需要

維護最後乙個點就夠了,因為動態樹的access操作可以隨意把乙個點變成這條鏈splay中的

最後一點,於是我們可以這樣合併:sum[u] = sum[ch[u][0]] + value[u] + sum[ch[u][1]]每次都

把左邊的都併入右邊的,這樣根節點的值就能表示這條鏈中最後乙個點的值了(類似中序

遍歷), 然後我們繼續把環上任意一邊刪去,將其中一點作為根節點,剩下的點作為乙個

special father,這樣我們access(sp)後就能得到sp自己的表示方法,然後通過討論k和b的

值來確定有沒有解或者多解的情況,這樣就解決了查詢問題,然後考慮修改操作,比較麻

煩,如果要改的點是乙個root,那麼直接修改sp就行了,否則我們要看要修改點是否在環

上,若在環上需要刪邊後先將root指向sp的邊加進去,然後看是否會出現新環,有就講新

父親作為sp,否則直接連虛邊。

#include#include#include#include#include#include#include#include#include#define inf 2147483640

#define eps 1e-9

#define maxn 30010

#define p 10007

using namespace std;

int n,q,ki,bi,fa[maxn],inv[maxn],pi[maxn],sp[maxn],ch[maxn][2];

bool vis[maxn],cir[maxn];

char op[3];

int get()

struct data

data(int x,int y)

}value[maxn],sum[maxn];

data operator * (data a,data b)

int ksm(int a,int b)

return ans;

}inline bool isroot(int x)

inline int findroot(int x)

void push_up(int x)

void rotate(int x)

fa[y] = x,fa[x] = z,fa[ch[x][d^1]] = y;

ch[y][d] = ch[x][d^1],ch[x][d^1] = y;

push_up(y),push_up(x);

}void splay(int x)

rotate(x); }}

void access(int x)

}void dfs(int u)

if(!vis[fa[u]]) dfs(fa[u]);

cir[u] = false;

}int query(int x)

void change()

} else

access(pt);

splay(pt);

int rootpt = findroot(pt);

if(rootpt == t) sp[t] = pt;

else

}pi[t] = pt;

}int main()

for(int i = 1;i <= n;i++)

if(!vis[i]) dfs(i);

q = get();

for(int i = 1;i <= q;i++)

else change();

}}

BZOJ2759 乙個動態樹好題 LCT

zhouzhendong 有n個未知數x 1.n 和n個等式組成的同餘方程組 x i k i x p i b i mod 10007 其中,k i b i x i 0,10007 z 你要應付q個事務,每個是兩種情況之一 一.詢問當前x a 的解 a a無解輸出 1 x a 有多解輸出 2 否則輸出...

BZOJ2759 乙個動態樹好題 LCT

題解 的確是動態樹好題 首先由於每個點只有乙個出邊 這個圖構成了基環內向樹 我們觀察那個同餘方程組 一旦形成環的話我們就能知道環上點以及能連向環上點的值是多少了 所以我們只需要用一種結構來維護兩個不是直接相連點的狀態 由於有刪邊連邊操作,比較容易想到lct 我們按照套路將它拆掉一條邊形成一顆樹 因為...

BZOJ 2759 一道動態樹的好題

一道好題的標準 從常規的知識點中敲擊出新火花,但並不是偏題。不卡常,不卡溢位 首先看乙個弱化的問題,乙個固定的 n 元 n項模方程怎麼求解每個變數。高斯消元?太慢啦!如果我們把x px連邊,我們可以得到乙個基環森林。對於每個聯通塊,找到環並求出環中某乙個變數的值,顯然當乙個變數的值求出來了,整個聯通...