有一顆 n 個點的帶權樹,點的編號是 1, 2, …, n. 樹有 (n - 1) 條邊,求樹上兩點之間的距離是2019的倍數的點對有多少?
點對距離計數:點分治
點分治關鍵是對cal函式進行修改,其他的基本不用改。如何靈活運用cal函式,主要還是要理解幾個變數的含義。根據點分治的過程,是不斷找重心,然後<1>求出每個點到重心的距離,同時用乙個陣列temp記錄這些距離,再對各個子樹進行分治,過程一樣。而cal函式就是在計算完<1>後,對temp進行操作,怎麼改,看具體的題目。這裡有個點需要注意,就是<1>操作會把所有點到重心的距離也算進去(加入傳入重心,就會有乙個零),所以temp必然會包含乙個len(len是calc的引數)。總的來說calc就是計算完其他點到某一點的距離後,對這些點的距離進行處理的中間過程。
cal改法
int cc[2019];
inline int calc(int x,int len)
2019倍數,很容易想到取餘處理,設b為重心,a->b+b->c=2019,就說明a->c是2019的倍數。
這樣其實還有乙個問題,就是重複計算。下面通過**,解釋如何處理。
a為重心,每一點到重心距離已經得到,但是通過cal函式會把b->a和c->a的距離也加上,所以需要把這種可能排除,我們最終的結果是,記錄每次分治不同子樹之間的距離,而同一子樹之間的點對需要排除。如何排除,ans-=cal(h,c)即可,對h的子節點到h的距離點對加上c,這些答案需要排除。
#includeusing namespace std;
#define ios ios::sync_with_stdio(false)
const int n = 20020, inf = 0x7f7f7f7f;
int n,head[n*2],num,tot,ans;//tot記錄當前子樹點數
int dis[n],flag[n],temp[n];
//dis記錄子樹每一點到根節點的距離,flag用於刪除根節點,temp總匯到根節點的距離
int size[n],max[n],root;
struct edge
g[n*2];
void add(int from,int to,int len)
inline void input(void)
}inline void dp(int fa,int cur)//求樹的重心
max[cur] = max( max[cur], tot - size[cur] );
if ( max[root] > max[cur] ) root = cur;
}inline void dfs(int fa,int cur)
}int cc[2019];
inline int calc(int x,int len)
inline void divide(int x)
return 0;
}
2019湖南「強智杯」省賽A題
bobo 寫了乙個 n 行 m 列的矩陣 ai,j.首先,他把所有元素 ai,j 1 i n,1 j m 設為 0.然後,他選了 4 個整數 x1,x2,y1,y2 滿足 1 x1 x2 n,1 y1 y2 m,並把滿足 x1 i x2,y1 j y2 的元素 ai,j 設為 1.給出 n 行 m ...
湖南省2017省賽A題
題目大意,給你n個數,要求你給出任意乙個排列,要求乙個數與左右的數的差值的絕對值大小大於d。直接遞推,設第乙個數為a,則第二個數顯然最大為n,那麼可以推出a n d 1,第三個數為a 1,第四個數為a d。以此可遞推出第i個數大小為,分奇偶性,i為奇數時,其為a i 1 2,偶數時,a d i 4 ...
2023年省賽I題 Thrall s Dream
2013年省賽i題 判斷單向聯通,用bfs 剪枝 從小到大跑,如果遇到之前跑過的點 也就是編號小於當前點的點 就o n 傳遞關係。bfs1 include2 include3 include4 include5 include6 include7 include 8 include9 include...