@M1saki
2017-07-27T23:13:46.000000Z
字数 2304
阅读 1309
acm
2017年7月
hdu
多校
组队训练
入口:2017 Multi-University Training Contest - Team 1
rank | ac/all | A | B | C | D | E | F | G | H | I | J | K | L |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
249/766 | 8/12 | O | O | Ø | . | . | Ø | . | Ø | Ø | . | O | Ø |
. | 尚未通过 | O | 当场通过 | Ø | 赛后通过 |
---|
nth_element()
由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉。所以问题就变为有个集合,每个集合里面都有一堆数字,要从每个集合中选择一个恰好一个数加起来。求所有的这样的和中,前大的是哪些。这就是一个经典问题了。
对所有集合两个两个进行合并,设当前合并的集合是和,合并的过程中用堆来求出当前的前大值是哪些。这样的复杂度看起来为,但如果合并的时候保证堆内的元素个数是新集合里的元素个数,设每个集合的大小分别为,则复杂度为。当都相等时取得最大值,所以实际复杂度为。
for(int i = 0; i < n; i++)
所以每个桶里面的id是递增的。
namespace IO {
const int MX = 4e7;
char buf[MX]; int c, sz;
void begin()
{
c = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(int &t)
{
while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
if(c >= sz) return false;
bool flag = 0; if(buf[c] == '-') flag = 1, c++;
for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
if(flag) t = -t;
return true;
}
}
void init()
{
fac[0] = 1; rep(i, 1, N) fac[i] = fac[i - 1] * i % p;
inv[0] = inv[1] = 1;
rep(i, 2, N) inv[i] = inv[p % i] * (p - p / i) % p;
rep(i, 3, N) inv[i] = inv[i - 1] * inv[i] % p;
}
LL C(int x, int y){ return fac[x] * inv[x - y] % p * inv[y] % p; }