[赛记] NOIP2024加赛1 && 多校A层冲刺NOIP2024模拟赛18
暴力错解大赛
玩游戏 82pts
乱糊的错解,正确性和时间复杂度都不对,但是拿了82pts;
对于正解,考虑从
那么贪心的思路是每次看看能不能将
但是这样只能将这两个指针移动到数组中最小的位置,考虑到后面的移动其实就是前面的移动的反方向,所以将数组倒过来再做一遍即可,时间复杂度
注意实现时有很多细节,要小心处理,注意边界,要不然一不小心时间复杂度就炸了;
注意为了保证时间复杂度,在实现过程中要时刻保证
点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int t;
int n, k;
long long a[500005], b[500005], c[500005], bmi, cmi;
int blen, clen, bpos, cpos;
int pos[2][500005];
bool ans;
void w() {
int l = 0, r = 0;
long long sum = 0;
while(1) {
if (l == bpos && r == cpos) break;
long long now = 0;
bool vis = false;
if (l != bpos) {
for (int i = pos[0][l]; i <= blen; i++) {
now = sum - b[l] + b[i];
if (now > 0) {
pos[0][l] = i;
break;
}
if (now <= sum) {
l = i;
sum = now;
vis = true;
break;
}
if (i == blen) pos[0][l] = blen;
}
}
if (r != cpos) {
for (int i = pos[1][r]; i <= clen; i++) {
now = sum - c[r] + c[i];
if (now > 0) {
pos[1][r] = i;
break;
}
if (now <= sum) {
r = i;
sum = now;
vis = true;
break;
}
if (i == clen) pos[1][r] = clen;
}
}
if (!vis) {
if (r == 0) {
r = 1;
sum = b[l] + c[r];
if (sum > 0) {
ans = false;
break;
}
} else if (l == 0) {
l = 1;
sum = b[l] + c[r];
if (sum > 0) {
ans = false;
break;
}
} else {
ans = false;
break;
}
}
}
}
int main() {
// freopen("in.in", "r", stdin);
// freopen("out.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> t;
while(t--) {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
bmi = 2e18;
cmi = 2e18;
cpos = bpos = 0;
for (int i = k; i >= 2; i--) {
blen++;
b[blen] = b[blen - 1] + a[i];
if (bmi >= b[blen]) {
bmi = b[blen];
bpos = blen;
}
}
b[blen + 1] = 2e18;
for (int i = k + 1; i <= n; i++) {
clen++;
c[clen] = c[clen - 1] + a[i];
if (cmi >= c[clen]) {
cmi = c[clen];
cpos = clen;
}
}
c[clen + 1] = 2e18;
for (int i = 0; i <= blen; i++) pos[0][i] = i + 1;
for (int i = 0; i <= clen; i++) pos[1][i] = i + 1;
ans = true;
w();
reverse(b + 1, b + 1 + blen);
reverse(c + 1, c + 1 + clen);
if (bpos != 0) bpos = blen - bpos + 1;
if (cpos != 0) cpos = clen - cpos + 1;
for (int i = 0; i <= blen; i++) pos[0][i] = i + 1;
for (int i = 0; i <= clen; i++) pos[1][i] = i + 1;
w();
if (c[1] == 2e18) c[1] = 0;
if (b[1] == 2e18) b[1] = 0;
if (c[1] + b[1] > 0) ans = false;
if (ans) cout << "Yes" << '\n';
else cout << "No" << '\n';
for (int i = 1; i <= blen + 1; i++) b[i] = 0;
for (int i = 1; i <= clen + 1; i++) c[i] = 0;
for (int i = 0; i <= blen; i++) pos[0][i] = 0;
for (int i = 0; i <= clen; i++) pos[1][i] = 0;
blen = 0;
clen = 0;
}
return 0;
}
矩形 20pts
不喷了,题解错了,std和题解写的根本不是一个东西;
然后我没发现,就按照题解打了三个树套树,然后就没然后了;
其实好像上个扫描线就行,没写,被题解恶心到了;
想看正解请自行翻阅其它博客;
选彩笔(rgb)60pts
赛时树套树求解三维数点 + 二分答案假了,60pts;
其实正解就是三维数点,先二分一个答案
那么可以 三维前缀和 + 容斥 处理,时间复杂度:
注意原题中有
经验:一般想到树套树的题都不用树套树做(可能能拿部分分或者错解骗分);
点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int n, kk;
int sum[266][266][266];
bool ck(int x) {
int su = 0;
for (int i = 1; i + x <= 256; i++) {
for (int j = 1; j + x <= 256; j++) {
for (int k = 1; k + x <= 256; k++) {
su = sum[i + x][j + x][k + x] - sum[i - 1][j + x][k + x] - sum[i + x][j - 1][k + x] - sum[i + x][j + x][k - 1] + sum[i - 1][j - 1][k + x] + sum[i - 1][j + x][k - 1] + sum[i + x][j - 1][k - 1] - sum[i - 1][j - 1][k - 1];
if (su >= kk) return true;
}
}
}
return false;
}
int main() {
freopen("rgb.in", "r", stdin);
freopen("rgb.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> kk;
int x, y, z;
for (int i = 1; i <= n; i++) {
cin >> x >> y >> z;
sum[++x][++y][++z]++;
}
for (int i = 1; i <= 256; i++) {
for (int j = 1; j <= 256; j++) {
for (int k = 1; k <= 256; k++) {
sum[i][j][k] += sum[i - 1][j][k] + sum[i][j - 1][k] + sum[i][j][k - 1] - sum[i - 1][j - 1][k] - sum[i - 1][j][k - 1] - sum[i][j - 1][k - 1] + sum[i - 1][j - 1][k - 1];
}
}
}
int l = 0;
int r = 225;
int ans = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if (ck(mid)) {
ans = mid;
r = mid - 1;
} else l = mid + 1;
}
cout << ans;
return 0;
}
兵蚁排序(sort)100pts
按照样例二模拟即可;
因为操作数
每次将大的一步一步向前交换过来就行;
正确性:因为这样会尽可能的保留
时间复杂度:
点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int t;
int n;
int a[500005], b[500005];
pair<int, int> an[500005];
int cnt;
int main() {
freopen("sort.in", "r", stdin);
freopen("sort.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> t;
while(t--) {
cin >> n;
cnt = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
cin >> b[i];
}
bool ans = true;
for (int i = 1; i <= n; i++) {
if (a[i] == b[i]) continue;
int mi = 0x3f3f3f3f;
int pos = 0;
for (int j = i; j <= n; j++) {
mi = min(mi, a[j]);
if (a[j] == b[i]) {
pos = j;
break;
}
}
if (mi < b[i] || !pos) {
ans = false;
break;
}
for (int j = pos - 1; j >= i; j--) {
an[++cnt] = {j, j + 1};
swap(a[j], a[j + 1]);
}
}
if (!ans) {
cout << -1 << '\n';
} else {
cout << 0 << '\n';
cout << cnt << '\n';
for (int i = 1; i <= cnt; i++) {
cout << an[i].first << ' ' << an[i].second << '\n';
}
}
}
return 0;
}
银行的源起(banking)10pts
按照题意模拟10pts;
考虑正解,首先考虑只有一个银行怎么做;
那么对于这种题,我们有一种套路,就是考虑每条边的贡献;
首先钦定
那么考虑走这条边的人数,发现银行只可能在子树里或者在子树外,所以一条边
考虑为什么是对的,因为在这棵树上,会有一个节点满足其儿子的
这个问题直接
考虑两个银行的情况,我们不难发现,原图中会有一条边没人走,因为这两个节点的最近的银行不一样,且只会有一条边,因为只有两个银行,原图只能被分成两个连通块;
那么我们可以枚举这一条边,然后对这两个连通块分别做一次
考虑如何优化;
对式子
设
原式可以化为(其中
那么对于一条边
对于
这样的话,我们在全局开两棵线段树记录所有的
因为我们要查询某一个子树,所以对子树在开两棵线段树,并且回溯的时候进行合并即可;
这样我们开了六棵线段树就解决了这个问题;
时间复杂度:
常数极大,只能拿82pts(具体见[PEP] 关于卡场);
点击查看代码
#pragma GCC optimize("Ofast")
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include <iostream>
#include <cstdio>
using namespace std;
#define FI(n) FastIO::read(n)
#define FO(n) FastIO::write(n)
#define Flush FastIO::Fflush()
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
inline int read(register char *s) {
while(bn) {
for (; bi < bn && buf[bi] <= ' '; bi = -~bi);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi &= 0;
}
register int sn=0;
while(bn) {
for (; bi < bn && buf[bi] > ' '; bi = -~bi) s[sn++] = buf[bi];
if(bi < bn) break;
bn = fread(buf,1,SIZE,stdin);
bi &= 0;
}
s[sn] &= 0;
return sn;
}
inline bool read(register int &x){
int n = read(str), bf = 0;
if(!n) return 0;
register int i=0;
(str[i] == '-') && (bf = 1, i = -~i);
(str[i] == '+') && (i = -~i);
for (x = 0; i < n; i = -~i) x = (x << 3) + (x << 1) + (str[i] ^ 48);
bf && (x = ~x + 1);
return 1;
}
inline bool read(register long long &x) {
int n = read(str), bf = 1;
if(!n) return 0;
register int i=0;
(str[i] == '-') && (bf = -1,i = -~i);
for (x = 0; i < n; i= -~i) x = (x << 3) + (x << 1) + (str[i] ^ 48);
(bf < 0) && (x = ~x + 1);
return 1;
}
inline void write(register int x) {
if(!x) obuf[opt++] = '0';
else {
(x < 0) && (obuf[opt++] = '-', x = ~x + 1);
register int sn = 0;
while(x) str[sn++] = x % 10 + '0', x /= 10;
for (register int i = sn - 1; i >= 0; i = ~-i) obuf[opt++] = str[i];
}
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void write(register long long x) {
if(!x) obuf[opt++] = '0';
else {
(x < 0) && (obuf[opt++] = '-', x = ~x + 1);
register int sn = 0;
while(x) str[sn++] = x % 10 + '0', x /= 10;
for (register int i = sn - 1; i >= 0; i = ~-i) obuf[opt++] = str[i];
}
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void write(register unsigned long long x){
if(!x) obuf[opt++] = '0';
else {
register int sn=0;
while(x) str[sn++] = x % 10 + '0', x /= 10;
for (register int i = sn - 1 ; i >= 0 ; i = ~-i)obuf[opt++] = str[i];
}
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void write(register char x) {
obuf[opt++] = x;
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void Fflush(){
opt && fwrite(obuf, 1, opt, stdout);
opt &= 0;
}
}
int t;
int n;
long long a[500005];
struct sss{
int t, ne;
long long w;
}e[500005];
int h[500005], cnt;
inline void add(int u, int v, long long ww) {
e[++cnt].t = v;
e[cnt].ne = h[u];
h[u] = cnt;
e[cnt].w = ww;
}
long long siz[500005];
long long tt;
int rt[500005], tot[2];
namespace top_tr{
struct sss{
int ls, rs;
long long sum;
}tr[2][6500005];
inline void push_up(long long s, long long id) {
tr[s][id].sum = tr[s][tr[s][id].ls].sum + tr[s][tr[s][id].rs].sum;
}
void add(long long s, int &id, long long l, long long r, long long pos, long long d) {
if (!id) id = ++tot[s];
if (l == r) {
tr[s][id].sum += d;
return;
}
long long mid = (l + r) >> 1;
if (pos <= mid) add(s, tr[s][id].ls, l, mid, pos, d);
else add(s, tr[s][id].rs, mid + 1, r, pos, d);
push_up(s, id);
}
long long merge(int s, long long x, long long y, long long l, long long r) {
if (!x || !y) return x + y;
if (l == r) {
tr[s][x].sum += tr[s][y].sum;
return x;
}
long long mid = (l + r) >> 1;
tr[s][x].ls = merge(s, tr[s][x].ls, tr[s][y].ls, l, mid);
tr[s][x].rs = merge(s, tr[s][x].rs, tr[s][y].rs, mid + 1, r);
push_up(s, x);
return x;
}
long long ask(int s, int id, long long L, long long R, long long l, long long r) {
if (l > r) return 0;
if (!id) return 0;
if (L >= l && R <= r) return tr[s][id].sum;
long long mid = (L + R) >> 1;
if (r <= mid) return ask(s, tr[s][id].ls, L, mid, l, r);
else if (l > mid) return ask(s, tr[s][id].rs, mid + 1, R, l, r);
else return ask(s, tr[s][id].ls, L, mid, l, mid) + ask(s, tr[s][id].rs, mid + 1, R, mid + 1, r);
}
}
long long ans;
void sfs(long long x, long long fa) {
siz[x] = a[x];
for (long long i = h[x]; i; i = e[i].ne) {
long long u = e[i].t;
if (u == fa) continue;
sfs(u, x);
siz[x] += siz[u];
rt[x] = top_tr::merge(0, rt[x], rt[u], 1, tt);
rt[x + n + 1] = top_tr::merge(1, rt[x + n + 1], rt[u + n + 1], 1, tt);
top_tr::add(0, rt[x], 1, tt, siz[u], e[i].w * siz[u]);
top_tr::add(1, rt[x + n + 1], 1, tt, siz[u], e[i].w);
}
}
void dfs(long long x, long long fa) {
for (long long i = h[x]; i; i = e[i].ne) {
long long u = e[i].t;
if (u == fa) continue;
top_tr::add(0, rt[0], 1, tt, siz[u], e[i].w * siz[u]);
top_tr::add(1, rt[0 + n + 1], 1, tt, siz[u], e[i].w);
top_tr::add(0, rt[1], 1, tt, siz[u], -e[i].w * siz[u]);
top_tr::add(1, rt[1 + n + 1], 1, tt, siz[u], -e[i].w);
dfs(u, x);
top_tr::add(0, rt[0], 1, tt, siz[u], -e[i].w * siz[u]);
top_tr::add(1, rt[0 + n + 1], 1, tt, siz[u], -e[i].w);
long long an = 0;
long long X = siz[u];
long long Y = siz[1] - siz[u];
long long sum = 0;
sum = top_tr::ask(0, rt[u + 2 * n + 1], 1, tt, 1, X / 2);
long long su = 0;
su = top_tr::ask(1, rt[u + 3 * n + 1], 1, tt, X / 2 + 1, tt);
su *= X;
su -= top_tr::ask(0, rt[u + 2 * n + 1], 1, tt, X / 2 + 1, tt);
an += sum + su;
sum = top_tr::ask(0, rt[1], 1, tt, 1, Y / 2) - top_tr::ask(0, rt[u + 2 * n + 1], 1, tt, 1, Y / 2);
su = top_tr::ask(1, rt[1 + n + 1], 1, tt, Y / 2 + 1, tt) - top_tr::ask(1, rt[u + 3 * n + 1], 1, tt, Y / 2 + 1, tt);
su *= Y;
su -= (top_tr::ask(0, rt[1], 1, tt, Y / 2 + 1, tt) - top_tr::ask(0, rt[u + 2 * n + 1], 1, tt, Y / 2 + 1, tt));
an += sum + su;
sum = top_tr::ask(0, rt[0], 1, tt, siz[u], Y / 2 + siz[u]);
long long ss = top_tr::ask(1, rt[0 + n + 1], 1, tt, siz[u], Y / 2 + siz[u]);
ss *= siz[u];
sum -= ss;
long long sss = top_tr::ask(1, rt[0 + n + 1], 1, tt, Y / 2 + siz[u] + 1, tt);
su = sss;
su *= Y;
su -= top_tr::ask(0, rt[0], 1, tt, Y / 2 + siz[u] + 1, tt);
ss = sss;
ss *= siz[u];
su += ss;
an += sum + su;
ans = min(ans, an);
top_tr::add(0, rt[1], 1, tt, siz[u], e[i].w * siz[u]);
top_tr::add(1, rt[1 + n + 1], 1, tt, siz[u], e[i].w);
rt[x + 2 * n + 1] = top_tr::merge(0, rt[x + 2 * n + 1], rt[u + 2 * n + 1], 1, tt);
rt[x + 3 * n + 1] = top_tr::merge(1, rt[x + 3 * n + 1], rt[u + 3 * n + 1], 1, tt);
top_tr::add(0, rt[x + 2 * n + 1], 1, tt, siz[u], e[i].w * siz[u]);
top_tr::add(1, rt[x + 3 * n + 1], 1, tt, siz[u], e[i].w);
}
}
int main() {
freopen("banking.in", "r", stdin);
freopen("banking.out", "w", stdout);
FI(t);
while(t--) {
FI(n);
for (long long i = 1; i <= n; i++) {
FI(a[i]);
tt += a[i];
}
long long x, y;
long long w;
ans = 2e18;
for (long long i = 1; i <= n - 1; i++) {
FI(x); FI(y); FI(w);
add(x, y, w);
add(y, x, w);
}
sfs(1, 0);
dfs(1, 0);
FO(ans);
FO('\n');
for (long long i = 1; i <= n; i++) {
h[i] = 0;
}
cnt = 0;
for (long long s = 0; s <= 1; s++) {
for (long long i = 1; i <= tot[s]; i++) {
top_tr::tr[s][i].ls = top_tr::tr[s][i].rs = top_tr::tr[s][i].sum = 0;
}
}
for (long long i = 0; i <= 4 * n + 1; i++) {
rt[i] = 0;
siz[i] = 0;
}
tt = 0;
tot[0] = tot[1] = 0;
}
Flush;
return 0;
}
upd: 经过作者的两个小时大力卡场以后,成功在1000ms内通过本题,详见[PEP] 还是卡场
以下是通过代码(可能再交一遍就过不了了。。。);
点击查看代码
#pragma GCC optimize("Ofast")
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include <iostream>
#include <cstdio>
using namespace std;
#define FI(n) FastIO::read(n)
#define FO(n) FastIO::write(n)
#define Flush FastIO::Fflush()
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
inline int read(register char *s) {
while(bn) {
for (; bi < bn && buf[bi] <= ' '; bi = -~bi);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi &= 0;
}
register int sn=0;
while(bn) {
for (; bi < bn && buf[bi] > ' '; bi = -~bi) s[sn++] = buf[bi];
if(bi < bn) break;
bn = fread(buf,1,SIZE,stdin);
bi &= 0;
}
s[sn] &= 0;
return sn;
}
inline bool read(register int &x){
int n = read(str), bf = 0;
if(!n) return 0;
register int i=0;
(str[i] == '-') && (bf = 1, i = -~i);
(str[i] == '+') && (i = -~i);
for (x = 0; i < n; i = -~i) x = (x << 3) + (x << 1) + (str[i] ^ 48);
bf && (x = ~x + 1);
return 1;
}
inline bool read(register long long &x) {
int n = read(str), bf = 1;
if(!n) return 0;
register int i=0;
(str[i] == '-') && (bf = -1,i = -~i);
for (x = 0; i < n; i= -~i) x = (x << 3) + (x << 1) + (str[i] ^ 48);
(bf < 0) && (x = ~x + 1);
return 1;
}
inline void write(register int x) {
if(!x) obuf[opt++] = '0';
else {
(x < 0) && (obuf[opt++] = '-', x = ~x + 1);
register int sn = 0;
while(x) str[sn++] = x % 10 + '0', x /= 10;
for (register int i = sn - 1; i >= 0; i = ~-i) obuf[opt++] = str[i];
}
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void write(register long long x) {
if(!x) obuf[opt++] = '0';
else {
(x < 0) && (obuf[opt++] = '-', x = ~x + 1);
register int sn = 0;
while(x) str[sn++] = x % 10 + '0', x /= 10;
for (register int i = sn - 1; i >= 0; i = ~-i) obuf[opt++] = str[i];
}
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void write(register unsigned long long x){
if(!x) obuf[opt++] = '0';
else {
register int sn=0;
while(x) str[sn++] = x % 10 + '0', x /= 10;
for (register int i = sn - 1 ; i >= 0 ; i = ~-i)obuf[opt++] = str[i];
}
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void write(register char x) {
obuf[opt++] = x;
(opt >= (SIZE >> 1)) && (fwrite(obuf, 1, opt, stdout), opt &= 0);
}
inline void Fflush(){
opt && fwrite(obuf, 1, opt, stdout);
opt &= 0;
}
}
int t;
int n;
long long a[500005];
struct sss{
int t, ne;
long long w;
}e[500005];
int h[500005], cnt;
inline void add(int u, int v, long long ww) {
e[++cnt].t = v;
e[cnt].ne = h[u];
h[u] = cnt;
e[cnt].w = ww;
}
long long siz[500005];
long long tt;
int rt[500005], tot;
inline pair<long long, long long> pjia(pair<long long, long long> xx, pair<long long, long long> yy) {
return {xx.first + yy.first, xx.second + yy.second};
}
namespace top_tr{
struct sss{
int ls, rs;
long long sum[2];
}tr[6500005];
void add(int &id, long long l, long long r, long long pos, long long d1, long long d2) {
if (!id) id = ++tot;
if (l == r) {
tr[id].sum[0] += d1;
tr[id].sum[1] += d2;
return;
}
long long mid = (l + r) >> 1;
if (pos <= mid) add(tr[id].ls, l, mid, pos, d1, d2);
else add(tr[id].rs, mid + 1, r, pos, d1, d2);
tr[id].sum[0] = tr[tr[id].ls].sum[0] + tr[tr[id].rs].sum[0];
tr[id].sum[1] = tr[tr[id].ls].sum[1] + tr[tr[id].rs].sum[1];
}
long long merge(long long x, long long y, long long l, long long r) {
if (!x || !y) return x + y;
if (l == r) {
tr[x].sum[0] += tr[y].sum[0];
tr[x].sum[1] += tr[y].sum[1];
return x;
}
long long mid = (l + r) >> 1;
tr[x].ls = merge(tr[x].ls, tr[y].ls, l, mid);
tr[x].rs = merge(tr[x].rs, tr[y].rs, mid + 1, r);
tr[x].sum[0] = tr[tr[x].ls].sum[0] + tr[tr[x].rs].sum[0];
tr[x].sum[1] = tr[tr[x].ls].sum[1] + tr[tr[x].rs].sum[1];
return x;
}
pair<long long, long long> ask(int id, long long L, long long R, long long l, long long r) {
if (l > r) return {0, 0};
if (!id) return {0, 0};
if (L >= l && R <= r) return {tr[id].sum[0], tr[id].sum[1]};
long long mid = (L + R) >> 1;
if (r <= mid) return ask(tr[id].ls, L, mid, l, r);
else if (l > mid) return ask(tr[id].rs, mid + 1, R, l, r);
else return pjia(ask(tr[id].ls, L, mid, l, mid), ask(tr[id].rs, mid + 1, R, mid + 1, r));
}
}
long long ans;
void sfs(long long x, long long fa) {
siz[x] = a[x];
for (long long i = h[x]; i; i = e[i].ne) {
long long u = e[i].t;
if (u == fa) continue;
sfs(u, x);
siz[x] += siz[u];
top_tr::add(rt[1], 1, tt, siz[u], e[i].w, e[i].w * siz[u]);
}
}
void dfs(long long x, long long fa) {
for (long long i = h[x]; i; i = e[i].ne) {
long long u = e[i].t;
if (u == fa) continue;
top_tr::add(rt[0], 1, tt, siz[u], e[i].w, e[i].w * siz[u]);
top_tr::add(rt[1], 1, tt, siz[u], -e[i].w, -e[i].w * siz[u]);
dfs(u, x);
top_tr::add(rt[0], 1, tt, siz[u], -e[i].w, -e[i].w * siz[u]);
long long an = 0;
long long X = siz[u];
long long Y = siz[1] - siz[u];
long long sum = 0;
pair<long long, long long> pi = top_tr::ask(rt[u + n + 1], 1, tt, 1, X / 2);
sum = pi.second;
long long su = 0;
su = top_tr::tr[rt[u + n + 1]].sum[0] - pi.first;
su *= X;
su -= (top_tr::tr[rt[u + n + 1]].sum[1] - pi.second);
an += sum + su;
pi = top_tr::ask(rt[1], 1, tt, 1, Y / 2);
pair<long long, long long> pii = top_tr::ask(rt[u + n + 1], 1, tt, 1, Y / 2);
sum = pi.second - pii.second;
su = (top_tr::tr[rt[1]].sum[0] - pi.first) - (top_tr::tr[rt[u + n + 1]].sum[0] - pii.first);
su *= Y;
su -= (top_tr::tr[rt[1]].sum[1] - pi.second) - (top_tr::tr[rt[u + n + 1]].sum[1] - pii.second);
an += sum + su;
pi = top_tr::ask(rt[0], 1, tt, siz[u], Y / 2 + siz[u]);
sum = pi.second;
long long ss = pi.first;
ss *= siz[u];
sum -= ss;
long long sss = top_tr::tr[rt[0]].sum[0] - pi.first;
su = sss;
su *= Y;
su -= (top_tr::tr[rt[0]].sum[1] - pi.second);
ss = sss;
ss *= siz[u];
su += ss;
an += sum + su;
ans = min(ans, an);
top_tr::add(rt[1], 1, tt, siz[u], e[i].w, e[i].w * siz[u]);
rt[x + n + 1] = top_tr::merge(rt[x + n + 1], rt[u + n + 1], 1, tt);
top_tr::add(rt[x + n + 1], 1, tt, siz[u], e[i].w, e[i].w * siz[u]);
}
}
int main() {
freopen("banking.in", "r", stdin);
freopen("banking.out", "w", stdout);
FI(t);
while(t--) {
FI(n);
for (long long i = 1; i <= n; i++) {
FI(a[i]);
tt += a[i];
}
long long x, y;
long long w;
ans = 2e18;
for (long long i = 1; i <= n - 1; i++) {
FI(x); FI(y); FI(w);
add(x, y, w);
add(y, x, w);
}
sfs(1, 0);
dfs(1, 0);
FO(ans);
FO('\n');
for (long long i = 1; i <= n; i++) {
h[i] = 0;
}
cnt = 0;
for (long long s = 0; s <= 1; s++) {
for (long long i = 1; i <= tot; i++) {
top_tr::tr[i].ls = top_tr::tr[i].rs = top_tr::tr[i].sum[0] = top_tr::tr[i].sum[1] = 0;
}
}
for (long long i = 0; i <= 4 * n + 1; i++) {
rt[i] = 0;
siz[i] = 0;
}
tt = 0;
tot = 0;
}
Flush;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?