[题解]我才是 Joker
2022-03-15 我才是 Joker
真没想到 T1 的 跑得这么快,预估是可能在常数上有一个 的缘故。另外 T3 还没有补,着实想不通了。
梦批糼 / Dream
我也不会念这个题目的名字。
其实我们的目标就是算出包含每个格子的合法的长方体的个数,最暴力的方法是 ,花费 代价枚举矩形,再用 枚举矩形中每一个元素算贡献。这种方法用高维前缀和优化就可以降为 ,还是有点距离。
如果我们将枚举的目标换成一个点,显然也不好,因为基础复杂度就是 ,再加上一些统计的实现,可能就变成 ,但是,如果我们将枚举一个点变成枚举一个面?显然基础复杂度是 的,但是我们只需要 去扫一遍这个面所对应的所有合法的极长柱就行了,对于极长柱的每一层,用一个差分来 记录答案即可。
因此总复杂度是 的,但是常数上有一个 ,这可能也是它可以过的原因。
/** @author __Elaina__ */
// #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define USING_FREAD
// #define NDEBUG
#include <cassert>
namespace Elaina {
/** その可憐な少女は魔女であり、旅人でした。 ―― そう、私です! */
#define rep(i, l, r) for(int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define repf(i, l, r) for (int i = (l), i##_end_ = (r); i < i##_end_; ++i)
#define drep(i, l, r) for(int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
/** @warning no forced type conversion */
#define rqr(x) ((x) * (x))
#define y0 FUCK_UP
#define y1 MOTHER_FUCKER
#define masdf(...) fprintf(stderr, __VA_ARGS__)
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef vector<int> vset;
template<class T> inline T fab(T x) { return x < 0 ? -x : x; }
template<class T> inline void chkmin(T& x, const T rhs) { x = std::min(x, rhs); }
template<class T> inline void chkmax(T& x, const T rhs) { x = std::max(x, rhs); }
#ifdef USING_FREAD
inline char qkgetc() {
# define BUFFERSIZE 1 << 20
static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
# undef BUFFERSIZE
}
# define CHARRECEI qkgetc()
#else
# define CHARRECEI getchar()
#endif
template<class T> inline T readret(T x) {
x = 0; int f = 0; char c;
while (!isdigit(c = CHARRECEI)) if(c == '-') f = 1;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
return f ? -x : x;
}
template<class T> inline void readin(T& x) {;
x = 0; int f = 0; char c;
while (!isdigit(c = CHARRECEI)) if (c == '-') f = 1;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
if (f) x = -x;
}
template<class T, class... Args> inline void readin(T& x, Args&... args) {
readin(x), readin(args...);
}
template<class T> inline void writln(T x, char c = '\n') {
if (x < 0) putchar('-'), x = -x;
static int __stk[55], __bit = 0;
do __stk[++__bit] = x % 10, x /= 10; while (x);
while (__bit) putchar(__stk[__bit--] ^ 48);
putchar(c);
}
} // namespace Elaina
using namespace Elaina;
#define int long long
const int Maxn = 60;
const int mod = 998244353;
inline void chkadd(int& x, int y) { if ((x += y) >= mod) x -= mod; }
inline int qkpow(int a, int q) {
int p = 1;
for (; q; q >>= 1, a = 1ll * a * a % mod)
if (q & 1) p = 1ll * p * a % mod;
return p;
}
int n, m, r, q, u;
int cnt[Maxn + 5][Maxn + 5][Maxn + 5];
int val[Maxn + 5][Maxn + 5][Maxn + 5];
inline void input() {
readin(n, m, r, q);
u = (1ll * n * (n + 1) * m * (m + 1) * r * (r + 1) / 8) % mod;
rep (i, 1, n) rep (j, 1, m) rep (k, 1, r)
readin(cnt[i][j][k]), cnt[i][j][k] ^= 1;
rep (i, 1, n) rep (j, 1, m) rep (k, 1, r)
readin(val[i][j][k]);
}
inline void prelude() {
rep (k, 1, r) rep (i, 1, n) rep (j, 1, m)
cnt[i][j][k] += cnt[i - 1][j][k] + cnt[i][j - 1][k] - cnt[i - 1][j - 1][k];
}
int buc[Maxn + 5];
int ans[Maxn + 5][Maxn + 5][Maxn + 5], valid = 0;
inline void solve() {
rep (lx, 1, n) rep (rx, lx, n) rep (ly, 1, m) rep (ry, ly, m) {
rep (i, 1, r) buc[i] = cnt[rx][ry][i]
- cnt[lx - 1][ry][i] - cnt[rx][ly - 1][i]
+ cnt[lx - 1][ly - 1][i];
// masdf("Now lx == %d, rx == %d, ly == %d, ry == %d\n", lx, rx, ly, ry);
for (int i = 1, j = 1; i <= r; i = ++j) if (!buc[i]) {
while (j < r && !buc[j + 1]) ++j;
valid += (j - i + 1) * (j - i + 2) >> 1;
rep (k, i, j) {
int x = (k - i + 1) * (j - k + 1);
ans[lx][ly][k] += x;
ans[rx + 1][ly][k] -= x;
ans[lx][ry + 1][k] -= x;
ans[rx + 1][ry + 1][k] += x;
}
}
}
rep (k, 1, r) rep (i, 1, n) rep (j, 1, m)
ans[i][j][k] += ans[i - 1][j][k] + ans[i][j - 1][k] - ans[i - 1][j - 1][k];
}
inline void calc() {
int res = 0, sum;
sum = qkpow(1ll * valid * qkpow(u, mod - 2) % mod, q);
valid = qkpow(valid, mod - 2);
rep (i, 1, n) rep (j, 1, m) rep (k, 1, r) {
int p = (1 + mod - qkpow((1 + mod - 1ll * ans[i][j][k] * valid % mod) % mod, q)) % mod;
p = 1ll * p * sum % mod;
chkadd(res, 1ll * p * val[i][j][k] % mod);
}
writln(res);
}
signed main() {
freopen("dream.in", "r", stdin);
freopen("dream.out", "w", stdout);
input();
prelude();
solve();
calc();
return 0;
}
等你哈苏德 / Wait
并不明白题目的意思。
区间覆盖并不需要关注整个数列,实际上我们只需要考察端点的情况就行了,换而言之,先转成前缀的情况,然后再关注每个端点的情况即可。在此基础上,注意到 "使得数轴上对于每个点,覆盖他的黑区间个数和白区间个数差的绝对值小于等于 1",这引导我们向欧拉路方面考虑,因为欧拉路满足这条路上每个点的入度与出度之差小于等于 1,刚好和这道题匹配。
离散化后,我们只需要关心每个端点处的差值。如果把区间 视为 和 之间连了一条无向边,染色视作是定向,我们可以发现这就是一个欧拉路径问题。我们把奇度数的点排序后依次连接,跑欧拉回路即可。
一部分线段染色相当于是混合图欧拉回路,跑网络流即可。由于这是个单位流量的图,所以 Dinic 算法可以快速跑出。
/** @author __Elaina__ */
// #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
#define USING_FREAD
// #define NDEBUG
#include <cassert>
namespace Elaina {
/** その可憐な少女は魔女であり、旅人でした。 ―― そう、私です! */
#define rep(i, l, r) for(int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define repf(i, l, r) for (int i = (l), i##_end_ = (r); i < i##_end_; ++i)
#define drep(i, l, r) for(int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
/** @warning no forced type conversion */
#define rqr(x) ((x) * (x))
#define y0 FUCK_UP
#define y1 MOTHER_FUCKER
#define masdf(...) fprintf(stderr, __VA_ARGS__)
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef vector<int> vset;
template<class T> inline T fab(T x) { return x < 0 ? -x : x; }
template<class T> inline void chkmin(T& x, const T rhs) { x = std::min(x, rhs); }
template<class T> inline void chkmax(T& x, const T rhs) { x = std::max(x, rhs); }
#ifdef USING_FREAD
inline char qkgetc() {
# define BUFFERSIZE 1 << 20
static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
# undef BUFFERSIZE
}
# define CHARRECEI qkgetc()
#else
# define CHARRECEI getchar()
#endif
template<class T> inline T readret(T x) {
x = 0; int f = 0; char c;
while (!isdigit(c = CHARRECEI)) if(c == '-') f = 1;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
return f ? -x : x;
}
template<class T> inline void readin(T& x) {;
x = 0; int f = 0; char c;
while (!isdigit(c = CHARRECEI)) if (c == '-') f = 1;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
if (f) x = -x;
}
template<class T, class... Args> inline void readin(T& x, Args&... args) {
readin(x), readin(args...);
}
template<class T> inline void writln(T x, char c = '\n') {
if (x < 0) putchar('-'), x = -x;
static int __stk[55], __bit = 0;
do __stk[++__bit] = x % 10, x /= 10; while (x);
while (__bit) putchar(__stk[__bit--] ^ 48);
putchar(c);
}
} // namespace Elaina
using namespace Elaina;
const int Maxn = 6e4;
const int Maxm = 1e6;
int m, n;
int l[Maxn + 5], r[Maxn + 5], w[Maxn + 5];
map<int, int> id;
int S, T, ncnt;
struct edge { int to, nxt, f; } e[Maxm << 1 | 1];
int tail[Maxn + 5], ecnt, cur[Maxn + 5];
inline void update(int i, int flow) { e[i].f -= flow, e[i ^ 1].f += flow; }
inline void add_edge(int u, int v, int f) {
e[ecnt] = edge{v, tail[u], f}; tail[u] = ecnt++;
e[ecnt] = edge{u, tail[v], 0}; tail[v] = ecnt++;
}
int prit[Maxn + 5], deg[Maxn + 5];
int corres[Maxn + 5];
int que[Maxn + 5], tl, hd;
int dis[Maxn + 5];
inline bool bfs() {
memset(dis + 1, 0x3f, ncnt << 2);
que[hd = tl = 1] = S, dis[S] = 0;
for (int u = que[hd]; hd++ <= tl; u = que[hd]) {
for (int i = tail[u], v; ~i; i = e[i].nxt) if (e[i].f) {
if (dis[v = e[i].to] == 0x3f3f3f3f) que[++tl] = v, dis[v] = dis[u] + 1;
}
}
return dis[T] != 0x3f3f3f3f;
}
int dfs(int u, int flow) {
if (u == T) return flow;
int used = 0, v;
for (int& i = cur[u]; ~i; i = e[i].nxt) if (e[i].f) {
if (dis[v = e[i].to] == dis[u] + 1) {
int ret = dfs(v, min(flow - used, e[i].f));
update(i, ret), used += ret;
if (used == flow) break;
}
}
return used;
}
inline int dinic() {
int mxf = 0;
while (bfs()) {
memcpy(cur + 1, tail + 1, ncnt << 2);
mxf += dfs(S, 0x3f3f3f3f);
}
return mxf;
}
signed main() {
// freopen("wait.in", "r", stdin);
// freopen("wait.out", "w", stdout);
readin(m, n), n = 0;
rep (i, 1, m) {
readin(l[i], r[i], w[i]), ++r[i];
id[l[i]] = id[r[i]] = 1;
}
for (auto& it: id) it.se = ++n;
ncnt = n;
S = ++ncnt, T = ++ncnt;
rep (i, 1, m) {
l[i] = id[l[i]], r[i] = id[r[i]];
prit[l[i]] ^= 1, prit[r[i]] ^= 1;
}
memset(tail, 0xff, sizeof tail);
mt19937 rnd((unsigned)time(NULL));
rep (i, 1, n) if (prit[i]) {
if (i == n) return puts("-1"), 0;
prit[i] ^= 1, prit[i + 1] ^= 1;
int t = rnd() & 1; // randomly orient the edge
++deg[i + t], --deg[i + (t ^ 1)];
add_edge(i + t, i + (t ^ 1), 1);
}
rep (i, 1, m) {
if (w[i] == 0) ++deg[l[i]], --deg[r[i]];
else if (w[i] == 1) ++deg[r[i]], --deg[l[i]];
else if (rnd() & 1) {
w[i] = 1;
++deg[r[i]], --deg[l[i]];
corres[i] = ecnt;
add_edge(r[i], l[i], 1);
}
else {
w[i] = 0;
++deg[l[i]], --deg[r[i]];
corres[i] = ecnt;
add_edge(l[i], r[i], 1);
}
}
int mxf = 0;
rep (i, 1, n) if (deg[i] != 0) {
if (deg[i] > 0) add_edge(S, i, deg[i] >> 1), mxf += deg[i] >> 1;
else add_edge(i, T, (-deg[i]) >> 1);
}
int res = dinic();
if (res ^ mxf) return puts("-1"), 0;
rep (i, 1, m) {
if (corres[i] && e[corres[i] ^ 1].f) w[i] ^= 1;
writln(w[i], " \n"[i == m]);
}
return 0;
}
喜欢最最痛 / Love
答案分成两个部分:对于一个 , 表示加 条额外边且 必须走 的代价,和前 个加边代价中的前 小和。而 必须走这 条边 在 林克卡特树 中也有体现 —— 实际上就是在这个树上选 条边不相交的链使得权值最大。
因此我们可以使用树形 DP 解决在树上选择 条最大权的边不交的链。时间复杂度为 或 :
int siz[Maxn + 5];
void dfs1(int u, int par) {
siz[u] = 1;
for (const auto& [v, w]: g[u]) if (v ^ par)
dfs1(v, u), siz[u] += siz[v];
}
ll f[Maxn + 5][Maxn + 5][2];
ll tmp[Maxn + 5][2];
void dfs2(int u, int par) {
f[u][0][0] = 0;
for (const auto& [v, w]: g[u]) if (v ^ par) {
dfs2(v, u);
for (int i = 0; i <= siz[u]; ++i)
tie(tmp[i][0], tmp[i][1]) = tie(f[u][i][0], f[u][i][1]);
for (int i = 0; i <= siz[u]; ++i) {
for (int j = 0; j <= siz[v]; ++j) {
chkmax(tmp[i + j][0], f[u][i][0] + f[v][j][0]);
chkmax(tmp[i + j][1], f[u][i][1] + f[v][j][0]);
chkmax(tmp[i + j][1], f[u][i][0] + f[v][j][1] + w);
chkmax(tmp[i + j][1], f[u][i][0] + f[v][j][0] + w);
chkmax(tmp[i + j + 1][0], f[u][i][1] + f[v][j][1] + w);
chkmax(tmp[i + j + 1][0], f[u][i][1] + f[v][j][0] + w);
chkmax(tmp[i + j + 1][0], f[u][i][0] + f[v][j][0] + w);
chkmax(tmp[i + j + 1][1], f[u][i][1] + f[v][j][0] + w);
chkmax(tmp[i + j + 1][1], f[u][i][0] + f[v][j][1] + w);
}
}
for (int i = 0; i <= siz[u]; ++i)
tie(f[u][i][0], f[u][i][1]) = tie(tmp[i][0], tmp[i][1]);
}
rep (j, 0, siz[u])
chkmax(f[u][j + 1][0], f[u][j][1]);
// rep (j, 0, siz[u]) {
// masdf("f[%d, %d, %d] == %lld\n", u, j, 0, f[u][j][0]);
// masdf("f[%d, %d, %d] == %lld\n", u, j, 1, f[u][j][1]);
// }
}
考虑优化选择 条不交且权值最大的链的过程,考虑使用与费用流类似的 悔过 操作,每次在这棵树上找直径,然后将直径的边翻转成负的。因为有负权边,所以考虑选择 LCT 或者树剖维护 DDP 来实现,时间复杂度应当为 .
至于对于一个 应当如何计算答案,注意到 是两个凸函数相加 —— 选择链的函数是斜率单减的,加额外边的函数是斜率单增的,因此我们可以在平衡树上二分出这个答案。
具体地,我们需要在树剖上维护一个点的直径,以及该区间的符号被整体翻转之后(填上负号)的直径,然后其他情况用类似线段树维护线段最值的方法即可,需要讨论的东西有点多,需要 仔细一点......代码实现用的全局平衡二叉树,因此复杂度是 的。
/** @author __Elaina__ */
#pragma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;
#define USING_FREAD
// #define NDEBUG
#include <cassert>
namespace Elaina {
/** その可憐な少女は魔女であり、旅人でした。 ―― そう、私です! */
#define rep(i, l, r) for(int i = (l), i##_end_ = (r); i <= i##_end_; ++i)
#define repf(i, l, r) for (int i = (l), i##_end_ = (r); i < i##_end_; ++i)
#define drep(i, l, r) for(int i = (l), i##_end_ = (r); i >= i##_end_; --i)
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define Endl putchar('\n')
#define whole(v) ((v).begin()), ((v).end())
#define bitcnt(s) (__builtin_popcount(s))
/** @warning no forced type conversion */
#define rqr(x) ((x) * (x))
#define y0 FUCK_UP
#define y1 MOTHER_FUCKER
#define masdf(...) fprintf(stderr, __VA_ARGS__)
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int, int> pii;
typedef vector<int> vset;
template<class T> inline T fab(T x) { return x < 0 ? -x : x; }
template<class T> inline void chkmin(T& x, const T rhs) { x = std::min(x, rhs); }
template<class T> inline void chkmax(T& x, const T rhs) { x = std::max(x, rhs); }
#ifdef USING_FREAD
inline char qkgetc() {
# define BUFFERSIZE 1 << 20
static char BUF[BUFFERSIZE], *p1 = BUF, *p2 = BUF;
return p1 == p2 && (p2 = (p1 = BUF) + fread(BUF, 1, BUFFERSIZE, stdin), p1 == p2) ? EOF : *p1++;
# undef BUFFERSIZE
}
# define CHARRECEI qkgetc()
#else
# define CHARRECEI getchar()
#endif
template<class T> inline T readret(T x) {
x = 0; int f = 0; char c;
while (!isdigit(c = CHARRECEI)) if(c == '-') f = 1;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
return f ? -x : x;
}
template<class T> inline void readin(T& x) {
x = 0; int f = 0; char c;
while (!isdigit(c = CHARRECEI)) if (c == '-') f = 1;
for (x = (c ^ 48); isdigit(c = CHARRECEI); x = (x << 1) + (x << 3) + (c ^ 48));
if (f) x = -x;
}
template<class T, class... Args> inline void readin(T& x, Args&... args) {
readin(x), readin(args...);
}
template<class T> inline void writln(T x, char c = '\n') {
if (x < 0) putchar('-'), x = -x;
static int __stk[55], __bit = 0;
do __stk[++__bit] = x % 10, x /= 10; while (x);
while (__bit) putchar(__stk[__bit--] ^ 48);
putchar(c);
}
template<class T> inline T listMax(const T& x) { return x; }
template<class T, class... Args> inline T listMax(const T& x, const Args&... args) {
return max(x, listMax(args...));
}
template<class T> inline T listMin(const T& x) { return x; }
template<class T, class... Args> inline T listMin(const T& x, const Args&... args) {
return min(x, listMin(args...));
}
} // namespace Elaina
using namespace Elaina;
const int Maxn = 1e5 * 3; // third times: threeDeglization & turning edge to nodes
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n, m; ll sum;
ll cost[Maxn + 5];
struct edge { int to, nxt; } e[Maxn * 2 + 5];
int tail[Maxn + 5], ecnt, ncnt;
ll val[Maxn + 5]; // the value of the node
inline void link(int u, int v) {
e[ecnt] = edge{v, tail[u]}; tail[u] = ecnt++;
e[ecnt] = edge{u, tail[v]}; tail[v] = ecnt++;
}
inline void input() {
readin(n, m), ncnt = n;
memset(tail, 0xff, sizeof tail);
int u, v, w;
rep (i, 2, n) {
readin(u, v, w), sum += w << 1;
val[++ncnt] = w; // turn edge to node
link(u, ncnt), link(ncnt, v);
}
rep (i, 1, m) readin(cost[i]);
}
/** <------------------------- ThreeDeglization -------------------------> */
vset g[Maxn + 5];
inline void add_edge(int u, int v) {
g[u].push_back(v), g[v].push_back(u);
}
void rebuild(int u, int par) {
vset son;
for (int i = tail[u], v; ~i; i = e[i].nxt) if ((v = e[i].to) != par)
rebuild(v, u), son.push_back(v);
if (son.size() < 3) {
for (const int& v: son) add_edge(u, v);
} else {
int len = son.size() - 2; // apply the node [ncnt + 1, ncnt + len]
repf (i, ncnt + 1, ncnt + len) add_edge(i, i + 1);
add_edge(u, son[0]), add_edge(u, ncnt + 1);
add_edge(ncnt + len, son.back()), son.pop_back();
repf (i, 1, son.size()) add_edge(ncnt + i, son[i]);
ncnt += len;
}
}
/** <------------------------- The Preparation for Building The GBBT - Part1 ------------------------->*/
int siz[Maxn + 5], wson[Maxn + 5], fa[Maxn + 5], dep[Maxn + 5];
int tp[Maxn + 5], dfn[Maxn + 5], id[Maxn + 5], tl[Maxn + 5], rt[Maxn + 5];
void dfs1(int u, int par) {
siz[u] = 1, fa[u] = par, dep[u] = dep[par] + 1;
for (const int& v: g[u]) if (v ^ par) {
dfs1(v, u), siz[u] += siz[v];
if (siz[v] > siz[wson[u]]) wson[u] = v;
}
}
/** <------------------------- Globally Balanced Binary Tree -------------------------> */
struct chain {
int u, v; ll d; // u is the shallower one
inline bool operator <(const chain& rhs) const {
if (d != rhs.d) return d < rhs.d;
else return u == rhs.u? v < rhs.v: u < rhs.u;
}
};
struct node {
int ls, rs;
int l, r; // the interval
ll val, sum; // the value and sum of the subtree
chain tol[2], tor[2], mxx[2]; // the to-left chain & to-right chain, and the max length of the cahin
int tag; // reverse tag
} tre[Maxn + 5];
typedef pair<int, ll> lFromChain; // light-from chain
lFromChain tolight[Maxn + 5]; // the endpos & length
chain golight[Maxn + 5]; // the longest chain when go into the subtre of light son
chain inlight[Maxn + 5]; // the longest chain in the light son
#define atls(i) tre[tre[i].ls]
#define atrs(i) tre[tre[i].rs]
inline void pushup(int i) {
tre[i].l = tre[i].r = id[i];
if (tre[i].ls) tre[i].l = atls(i).l;
if (tre[i].rs) tre[i].r = atrs(i).r;
tre[i].sum = atls(i).sum + atrs(i).sum + tre[i].val;
for (int t = 0, sg = 1; t < 2; ++t, sg *= -1) {
tre[i].tol[t] = listMax(
atls(i).tol[t],
chain{tre[i].l, atrs(i).tol[t].v, (tre[i].val + atls(i).sum) * sg + atrs(i).tol[t].d},
chain{tre[i].l, tolight[id[i]].fi, (tre[i].val + atls(i).sum) * sg + tolight[id[i]].se}
);
tre[i].tor[t] = listMax(
atrs(i).tor[t],
chain{tre[i].r, atls(i).tor[t].v, atls(i).tor[t].d + (tre[i].val + atrs(i).sum) * sg},
chain{tre[i].r, tolight[id[i]].fi, tolight[id[i]].se + (tre[i].val + atrs(i).sum) * sg}
);
tre[i].mxx[t] = listMax(
atls(i).mxx[t],
atrs(i).mxx[t],
chain{atls(i).tor[t].v, tolight[id[i]].fi, atls(i).tor[t].d + tre[i].val * sg + tolight[id[i]].se},
chain{tolight[id[i]].fi, atrs(i).tol[t].v, tre[i].val * sg + tolight[id[i]].se + atrs(i).tol[t].d},
chain{atls(i).tor[t].v, atrs(i).tol[t].v, atls(i).tor[t].d + atrs(i).tol[t].d + tre[i].val * sg},
inlight[id[i]]
);
}
}
int build(int l, int r) {
if (l > r) return 0;
int pivot = l, sum = 0, pre = 0;
rep (i, l, r) sum += siz[id[i]] - siz[wson[id[i]]];
rep (i, l, r) {
pre += siz[id[i]] - siz[wson[id[i]]];
if ((pre << 1) > sum) { pivot = i; break; }
}
tre[pivot].l = tre[pivot].r = id[pivot];
tre[pivot].val = tre[pivot].sum = val[id[pivot]];
tre[pivot].mxx[0] = tre[pivot].tol[0] = tre[pivot].tor[0] = chain{pivot, tolight[pivot].fi, tolight[pivot].se + val[pivot]};
tre[pivot].mxx[1] = tre[pivot].tol[1] = tre[pivot].tor[1] = chain{pivot, tolight[pivot].fi, tolight[pivot].se - val[pivot]};
chkmax(tre[pivot].mxx[0], inlight[pivot]);
chkmax(tre[pivot].mxx[1], inlight[pivot]);
tre[pivot].ls = build(l, pivot - 1);
tre[pivot].rs = build(pivot + 1, r);
return pushup(pivot), pivot;
}
inline void uploadInfo(int u) {
if (u != tp[u] || !fa[u]) return ; // no fake father
golight[fa[u]] = tre[rt[u]].tol[0];
inlight[fa[u]] = tre[rt[u]].mxx[0];
}
inline void updateLight(int u) {
if (!u) return ;
tolight[u] = {u, 0};
if (golight[u].d > tolight[u].se)
tolight[u] = {golight[u].v, golight[u].d};
}
inline void flip(int i) {
if (!i) return ;
tre[i].val = -tre[i].val, tre[i].sum = -tre[i].sum;
swap(tre[i].tol[0], tre[i].tol[1]);
swap(tre[i].tor[0], tre[i].tor[1]);
swap(tre[i].mxx[0], tre[i].mxx[1]);
tre[i].tag ^= 1;
}
inline void pushdown(int i) {
if (!tre[i].tag) return ;
flip(tre[i].ls), flip(tre[i].rs), tre[i].tag = 0;
}
inline void modify(int i, int l, int r, int ql, int qr) {
if (!i || ql > qr) return ;
if (ql <= l && r <= qr) return flip(i);
pushdown(i);
if (ql <= i && i <= qr) tre[i].val = -tre[i].val;
if (ql < i) modify(tre[i].ls, l, i - 1, ql, qr);
if (i < qr) modify(tre[i].rs, i + 1, r, ql, qr);
pushup(i);
}
inline void updateAll(int i, int to) {
if (!i) return ;
pushdown(i);
if (to < i) updateAll(tre[i].ls, to);
else if (i < to) updateAll(tre[i].rs, to);
pushup(i);
}
/** <------------------------- The Preparation for Building The GBBT - Part2 -------------------------> */
void dfs2(int u) {
dfn[u] = ++*dfn, id[dfn[u]] = u, tl[tp[u]] = u;
tolight[u] = {u, 0}, golight[u] = chain{-1, -1, 0};
if (wson[u]) {
tp[wson[u]] = tp[u]; dfs2(wson[u]);
for (const int& v: g[u]) if (v ^ fa[u] && v ^ wson[u])
dfs2(tp[v] = v);
}
if (u == tp[u]) {
rt[u] = build(dfn[u], dfn[tl[u]]);
uploadInfo(u), updateLight(fa[u]);
}
}
inline void rever(int u, int v) {
if (u < 1 || v < 1) return ;
while (tp[u] ^ tp[v]) {
if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
modify(rt[tp[u]], dfn[tp[u]], dfn[tl[tp[u]]], dfn[tp[u]], dfn[u]);
uploadInfo(tp[u]);
updateLight(u = fa[tp[u]]);
updateAll(rt[tp[u]], dfn[u]);
}
if (dep[u] > dep[v]) swap(u, v);
modify(rt[tp[u]], dfn[tp[u]], dfn[tl[tp[u]]], dfn[u], dfn[v]);
while (fa[tp[u]]) {
uploadInfo(tp[u]);
updateLight(u = fa[tp[u]]);
updateAll(rt[tp[u]], dfn[u]);
}
updateLight(tp[u]);
}
ll ans[Maxn + 5], dp[Maxn + 5];
namespace saya {
mt19937 rnd(0xcbdd1);
int son[Maxn + 5][2];
ll val[Maxn + 5], sum[Maxn + 5];
int siz[Maxn + 5];
unsigned rd[Maxn + 5];
int ncnt, rt;
inline int newnode(ll v) {
int x = ++ncnt;
val[x] = sum[x] = v, siz[x] = 1;
rd[x] = ((rnd() ^ rnd() & rnd() | rnd()) & 0x7fff) << 15 | (rnd() ^ rnd() & rnd() | rnd());
return x;
}
struct mypair {
int c[2];
inline int& operator [](int id) { return c[id]; }
};
inline void pushup(int x) {
siz[x] = siz[son[x][0]] + siz[son[x][1]] + 1;
sum[x] = sum[son[x][0]] + sum[son[x][1]] + val[x];
}
mypair split(int x, ll k) {
if (!x) return {0, 0};
int d = val[x] < k;
auto ret = split(son[x][d], k);
son[x][d] = ret[d ^ 1], ret[d ^ 1] = x;
pushup(x);
return ret;
}
int merge(int x, int y) {
if (!x || !y) return x ^ y;
int ret = 0xcbdd1;
if (rd[x] < rd[y]) son[x][1] = merge(son[x][1], y), pushup(ret = x);
else son[y][0] = merge(x, son[y][0]), pushup(ret = y);
return ret;
}
inline void insert(ll k) {
auto tmp = split(rt, k);
rt = merge(merge(tmp[0], newnode(k)), tmp[1]);
}
inline ll query(int x, int cur) {
if (!x) return dp[cur];
int lsz = siz[son[x][0]] + 1;
ll calc = val[x] + dp[cur + lsz] - dp[cur + lsz - 1];
if (calc >= 0) return query(son[x][0], cur);
return sum[son[x][0]] + val[x] + query(son[x][1], cur + lsz);
}
} // namespace saya
inline void solve() {
ans[0] = dp[0] = sum;
rep (i, 1, m) {
chain diamet = tre[rt[1]].mxx[0];
dp[i] = dp[i - 1] - diamet.d;
rever(diamet.u, diamet.v);
}
rep (i, 1, m) {
saya::insert(cost[i]);
ans[i] = saya::query(saya::rt, 0);
}
rep (i, 0, m) writln(ans[i], " \n"[i == m]);
}
signed main() {
freopen("love.in", "r", stdin);
freopen("love.out", "w", stdout);
input();
rebuild(1, 0);
tre[0].mxx[0] = tre[0].tol[0] = tre[0].tor[0] = chain{0, 0, -inf};
tre[0].mxx[1] = tre[0].tol[1] = tre[0].tor[1] = chain{0, 0, -inf};
dfs1(1, 0);
dfs2(tp[1] = 1);
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
2021-03-15 [BZOJ4664]count