確實是簡單題。邊權和最小顯然是最小生成樹。對於一條非樹邊,加到樹裡面一定會構成乙個環,那麼環上的樹邊的邊權就一定不能超過這條非樹邊。所以對最小生成樹進行重鏈剖分,對於一條非樹邊 \((u_i,v_i)\) ,對鏈 \(u_i\to v_i\) 進行 \(modify\),維護乙個最小值。而對於一條非樹邊要想成為樹邊,就至少需要把其邊權修改成這條鏈上樹邊的最大值,亦可用樹剖隨便維護一下。複雜度 \(o(m\log^2n)\)。
考場上空間開小了,爆成 60。以為開夠了後就過了,才發現 \(m\) 是 \(1e6\),\(n\) 是 \(1e5\)。雖然開的 \(6\) 秒,依舊過不了,只有 \(90\) 分。又想了想發現可以用樹上差分加倍增做,但不想重構**了,直接加了乙個火車頭過了。
#include#include#includeusing namespace std;
#define m 1000007
#define n 100007
#define inf 1000000000
#define lid id<<1
#define rid id<<1|1
inline char nc()
inline int read()
while(c>='0'&&c<='9')
return flag? x:-x;
}struct nodet[n<<2];
struct line
bool operator
}inline void dfs2(int u,int tp)
}inline int max(int x,int y)
inline int min(int x,int y)
}inline void pushup(int id,int val)
inline void pushdown(int id)
int l,r,val;
inline void modify(int id,int lf,int rf)
}inline void modify_path(int u,int v)
inline int query(int id,int lf,int rf,int op)
}inline int query_path(int u,int v,int op)
int ans[m];
bool vis[m];
int main()
memset(fa,0,sizeof(fa));
cnt=0,fa[1]=1,dep[1]=1,dfs1(1);
for(register int i=1;i<=m;i++)
dfs2(1,1); build(1,1,n);
for(register int i=1;i<=m;i++)
for(register int i=1;i<=m;i++)
if(vis[i]) ans[l[i].pos]=query_path(l[i].x,l[i].y,2);
for(register int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
2020多校聯考 簡單題
2020.11.23 題目只要求求出 c 的值,它就提示我們 c 和 a b 的值沒有太大關係。照著這個思路我們把 a b 合併一下,搞成二元組。對 a b leq c a b,c to 2 a b c a b 對 a b c a b,c to a b c,2c 我們發現 ab 始終可以並在一起,乾...
2020多校聯考 樹
沒有定根就非常的離譜,後來告訴根直接就是 1 先考慮鏈上怎麼做,顯然維護乙個單調棧,求出第乙個比當前數大的位置,然後倍增即可。再放在樹上怎麼做?依舊維護單調棧,但這次不能暴力地彈掉棧頂元素了,因為這樣的複雜度是假的。因為單調棧有單調性,所以直接在單調棧內二分出單調棧彈得不能再彈的位置,然後修改 to...
2020多校聯考 手套
有兩個可重集 a 和 b 每個集合裡有若干元素,每種元素有若干個。可以選擇從 a 集中等概率隨機選 x 個到 c 集 從 b 中等概率隨機選擇 y 個到 d 使得一定會使 c 和 d 有交。最小化 x y 在 x y 相等時最小化 x 因為要使得一定有交,所以考慮選了一定數目後,沒有交的最壞情況。最...