給定一棵 \(n\) 個節點的樹,求前 \(m\) 條最長路徑的長度。
序號 \(n\)
\(m\) 資料型別
1 10 3 暴力
2 233 23333 暴力
3 2000 300000 暴力
4 2000 300000 暴力
5 50000 1 隨機生成
6 7798 17798 隨機生成
7 7798 27798 隨機生成
8 7798 37798 隨機生成
9 50000 300000 1-n 順序輸入的鏈
10 50000 300000 以 1 為根的菊花圖
估分:\(70\)
實測:\(40\)
因為寫鏈時腦子抽了居然用了 \(map\) 然後空間炸了,還有判斷是否是鏈那裡寫錯了一點導致第乙個點還掛了。。。
對於鏈:先把 \(1-i(i <= n)\) 的所有鏈加入堆,然後取出最大的輸出,再把這條鏈刪掉上面那條邊,扔進堆裡
對於菊花圖:把每條邊排個序,可以構造乙個矩形,矩形的 \((x, y)\) 代表的是 \(d[x] + d[y]\) ,\(d[i]\) 是 \(i\) 到 \(1\) 的邊權,先把第一行全部扔進堆裡,取最大的輸出,再把 \((x + 1, y)\) 上的值扔進去
對於暴力:列舉每條鏈,用 \(lca\) 維護鏈的長度
正解:點分治,把每棵子樹做超級鋼琴的做法,用 \(st\) 表或者線段樹維護
不知道如何下手...照著網上的一篇題解打的
#include#define f(i, x, y) for(int i = x; i <= y; ++i)
using namespace std;
int read();
const int n = 5e4 + 5;
int n, m;
int sum, root, mx, id, l, r;
int head[n], cnt, ver[n << 1], edge[n << 1], nxt[n << 1];
int st[n * 20][21], d[n * 20], size[n], vis[n], dis[n];
struct nodep[n * 20];
struct use;
priority_queueq;
bool operator<(use a,use b)
void add(int x, int y, int z)
void get_root(int x, int fa)
maxn = max(maxn, sum - size[x]);
if(maxn < mx) mx = maxn, root = x;
}void dfs(int x, int fa)
; for(int i = head[x]; i; i = nxt[i])
if(! vis[ver[i]] && ver[i] != fa)
dis[ver[i]] = dis[x] + edge[i], dfs(ver[i], x);
}void solve(int x)
, l = r = id;
for(int i = head[x]; i; i = nxt[i])
if(! vis[ver[i]])
dis[ver[i]] = edge[i], dfs(ver[i], x), r = id;
for(int i = head[x]; i; i = nxt[i])
if(! vis[ver[i]])
root = 0, sum = size[ver[i]], mx = int_max, get_root(ver[i], 0), solve(root);
}int query(int l, int r)
void pre());}
int main()
); if(k.r - k.mq) q.push(use);
} return 0;
}int read()
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
給定 \(n\) 個點(編號為 \(1-n\)),由 \(m\) 條無向邊連線的圖,每個點有兩個權值 \(ax\),\(bx\),給定乙個值 \(k\),要求在圖中選出大小為 \(k\) 的點集 \(s\),使 \(s\) 中任意兩點間存在僅經過在 \(s\) 中的點的路徑。
設 \(as\) 為點集 \(s\) 中 \(ax\) 的最大值,\(bs\) 為 \(s\) 中 \(bx\) 的最大值,求乙個合法的 \(s\) 使得 \(as+bs\) 最小。
原本打了乙個暴力的結果只有 \(12pts\)
\(/kk\)
正解:星球上有 \(n\) 個城市,標號為 \(1-n\),用 \(n-1\) 條雙向通道連線,保證任意兩個城市能互相到達。
生化危機爆發了!但由於**安全能力有限,安全區只包括在標號 \(l\) 到 \(r\) 的城市,你現在在城市 \(x\),想知道最近的安全城市的距離。
對於 \(30\%\) 的資料, \(n,q<=1000\);
另有 \(20\%\) 的資料,保證第城市 \(2-n\) 均可直接到達城市 \(1\);
另有 \(10\%\) 的資料,保證城市 i(1<=i<=n-1)可直接到達城市 \(i+1\);
對於 \(100\%\) 的資料, \(n,q<=100000\),\(li<=ri\),任意兩個城市的距離小於 \(10^9\)。
估分:\(60\)
實測:\(60\)
對於鏈:如果在 \([l \ ,\ r]\) 裡輸出 \(0\),不在則取 \(min(d[x][l] \ , \ d[x][r])\),\(d[i][j]\) 表示 \(i \ , \ j\) 之間距離
對於菊花圖:用 \(st\) 表維護 \(l-r\) 的每個點到 \(1\) 的路徑的 \(min\) 值,分情況討論即可
對於其他:直接 \(dfs\) ,加個剪枝,當當前距離大於 \(ans\) 時返回,可以水過此題
正解:要用到點分治還是點分樹來著,我分不太清這兩個,大概就是,拆成很多個子樹,在每個子樹上都做乙個動態加點線段樹,維護此子樹里在 \(l-r\) 中的點到子樹根的最小值,用此最小值加上子樹根到 \(x\) 的值,更新 \(ans\),然後再往上跳,找新的子樹根
(正解只存在於口胡233
#include#define ll long long
#define f(i, x, y) for(int i = x; i <= y; ++i)
using namespace std;
ll read();
const int n = 1e6 + 5;
const int m = n << 1;
const ll inf = 1e18 + 5;
int n, q, flag;
ll x, y, z, l, r, ans;
ll head[n], cnt, ver[m], nxt[m];
ll edge[m], d[n], st[n][22], ok[n];
void add(ll x, ll y, ll z)
void dfs1(int x, int fa)
void solve_1()// 鏈
exit(0);
}void solve_2()// 菊花圖
exit(0);
}void dfs3(ll x, ll fa, ll dis)
for(int i = head[x]; i; i = nxt[i])
if(ver[i] != fa)
dfs3(ver[i], x, dis + edge[i]);
}void solve_3()// 其他
} int main()
q = read();
if(! flag) solve_1();
f(i, 2, n) if(ver[head[i]] != 1) flag = 0;
if(flag) solve_2();
solve_3();
return 0;
}ll read()
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
NOIP模擬賽考試總結
noip模擬賽考試總結 這兩天我們進行了以小奇為主題的noip模擬賽 考試總結 第一題看出是乙個dp,但是前面的決策對後面有影響,百思不得其解時想到後面決策對前面沒有影響,所以從後面開始dp,每步取max。第二題看了半天都不會,交了乙個暴力演算法,得了0分,因為我把字首和取模了,比如 1 2 3 4...
2019 11 12 CSP模擬賽 考前小總結
離聯賽只有幾天了,也馬上就要回歸文化課了。有點捨不得,感覺自己的水平剛剛有點起色,卻又要被抓回文化課教室了,真想在機房再賴幾天啊。像19 11 11那場的簡單題,自己還是能敲出一些比較穩的暴力,雖然不見得能拿很高檔的暴力或者打出正解,但至少不會掛分,最後能拿到的分數也還能看。但是一上點難度,或者不對...
20151006模擬賽總結
今天上午去一中,又考了個模擬賽。這次的題有點考思維。我感覺這個第一題難度稍微大了點。一般noip第一題要麼是簡單的模擬,要麼是裸的簡單演算法,這次的第一題要自己構造演算法,並且還是列舉和貪心套在一起。我開始想的是列舉 揹包,複雜度為n 3,但是資料範圍沒給出三次方的分。於是我就覺得不靠譜。然後發現列...