社区讨论
用int正确longlongRE,线段树模拟费用流求条
P4694[PA 2013] Raper参与者 4已保存回复 6
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 6 条
- 当前快照
- 1 份
- 快照标识符
- @mjz57qfu
- 此快照首次捕获于
- 2026/01/04 10:59 2 个月前
- 此快照最后确认于
- 2026/01/07 20:55 上个月
测样例显示,用int可以输出正确结果,longlong就会RE,而且这题的数据范围必须开long long,RE的返回值是11
现在提交分数是16pts
不知道有没有dalao可以分辨这是什么情况,是什么神秘UB嘛?
CPP#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 5e5 + 10;
ll a[N], b[N];
struct node
{
ll x, y;
bool operator<(const node &t) const
{
return a[x] + b[y] < a[t.x] + b[t.y];
}
};
struct GG
{
ll ma, mb; // 区间花费最小的a[ma]和b[mb]
ll la, lb; // 满足a[la]是l-la的严格前缀最小值的最小值,b[lb]是r-lb的严格后缀最小值的最小值
ll tag, mn; // 区间加减的tag和区间最小值mn
node va, vb, vc; // va是满足()的,vb是满足)(的(前提要求符合严格大于区间最小值,vc是)(不考虑要求
};
struct SEG
{
GG tr[N * 4];
GG pushup(GG L, GG R)
{
GG tmp;
tmp.tag = 0;
if (a[L.ma] < a[R.ma]) // 找最小a
tmp.ma = L.ma;
else
tmp.ma = R.ma;
if (b[L.mb] < b[R.mb]) // 找最小b
tmp.mb = L.mb;
else
tmp.mb = R.mb;
tmp.mn = min(L.mn, R.mn); // 取区间最小值
tmp.va = min(node{L.ma, R.mb}, min(L.va, R.va)); // 满足要求的最优情况1
tmp.vc = min(node{R.ma, L.mb}, min(L.vc, R.vc)); // 可能不满足要求的情况2
tmp.vb = min(L.vb, R.vb);
if (L.mn > R.mn)
{
tmp.vb = min(min(tmp.vb, L.vc), node{R.la, L.mb}); // 因为R的最小值小于L,所以L的vc一定就合法,同时{R.la,L.mb}一定合法
if (a[L.ma] < a[R.la])
tmp.la = L.ma;
else
tmp.la = R.la;
tmp.lb = R.lb;
}
else if (L.mn < R.mn)
{
tmp.vb = min(min(tmp.vb, R.vc), node{R.ma, L.lb}); // 同上
if (a[L.lb] < a[R.mb])
tmp.la = L.lb;
else
tmp.la = R.mb;
tmp.la = R.la;
}
return tmp;
}
void pushdown(ll u)
{
if (tr[u].tag)
{
tr[u << 1].tag += tr[u].tag, tr[u << 1].mn += tr[u].tag;
tr[u << 1 | 1].tag += tr[u].tag, tr[u << 1 | 1].mn += tr[u].tag;
tr[u].tag = 0;
}
}
void build(ll u, ll l, ll r)
{
if (l == r)
{
tr[u] = {l, l, l, 0, 0, 0, node{l, l}, node{0, 0}, node{l, l}};
return;
}
ll mid = (l + r) >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
tr[u] = pushup(tr[u << 1], tr[u << 1 | 1]);
}
void modify(ll u, ll l, ll r, ll p)
{
if (l == r)
return;
pushdown(u);
ll mid = (l + r) >> 1;
if (p <= mid)
modify(u << 1, l, mid, p);
else
modify(u << 1 | 1, mid + 1, r, p);
tr[u] = pushup(tr[u << 1], tr[u << 1 | 1]);
}
void modify1(ll u, ll l, ll r, ll L, ll R, ll p)
{
if (l > R or L > r)
return;
if (L <= l and r <= R)
{
tr[u].tag += p, tr[u].mn += p;
return;
}
pushdown(u);
ll mid = (l + r) >> 1;
if (L <= mid)
modify1(u << 1, l, mid, L, R, p);
if (R > mid)
modify1(u << 1 | 1, mid + 1, r, L, R, p);
tr[u] = pushup(tr[u << 1], tr[u << 1 | 1]);
}
} T;
ll n, k;
int main()
{
cin >> n >> k;
for (ll i = 1; i <= n; i++)
cin >> a[i];
for (ll i = 1; i <= n; i++)
cin >> b[i];
a[0] = b[0] = 0x3f3f3f3f3f3f3f3f;
T.build(1, 1, n);
ll ans = 0;
while (k--)
{
ll x, y, del;
if (T.tr[1].va < T.tr[1].vb)
{
x = T.tr[1].va.x, y = T.tr[1].va.y, del = 1;
}
else
{
x = T.tr[1].vb.x, y = T.tr[1].vb.y, del = -1;
}
ans += a[x] + b[y];
a[x] = b[y] = 0x3f3f3f3f;
T.modify(1, 1, n, x), T.modify(1, 1, n, y);
T.modify1(1, 1, n, min(x, y), max(x, y) - 1, del);
}
cout << ans;
}
回复
共 6 条回复,欢迎继续交流。
正在加载回复...