CF1051G Distinctification
CF1051G Distinctification
显然,最后的 集合是唯一的。
若 两两不同,则有多个 连续的值域段,段内满足 递减最优。
否则,将 平铺往后,与后面的值域段合并即可,并查集维护。
考虑计算答案,发现其只与最终结果相关,为 ,线段树维护值域块答案即可。
时间复杂度 。
#include <bits/stdc++.h>
using namespace std;
//#define int long long
typedef long long ll;
#define ha putchar(' ')
#define he putchar('\n')
inline int read()
{
int x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(ll x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
const int _ = 4e5 + 10;
int n, cnt, a[_], b[_], fa[_], rt[_];
bool vis[_];
ll s[_], ans;
struct Tr
{
int siz, c[2];
ll sum, val;
} t[_ * 30];
void pushup(int o)
{
t[o].sum = t[t[o].c[0]].sum + t[t[o].c[1]].sum;
t[o].siz = t[t[o].c[0]].siz + t[t[o].c[1]].siz;
t[o].val = t[t[o].c[0]].val + t[t[o].c[1]].val + 1ll * t[t[o].c[0]].sum * t[t[o].c[1]].siz;
}
void upd(int &o, int l, int r, int p)
{
if (!o)
o = ++cnt;
if (l == r)
{
t[o].sum = t[o].val = p;
t[o].siz = 1;
return;
}
int mid = (l + r) >> 1;
if (p <= mid)
upd(t[o].c[0], l, mid, p);
else
upd(t[o].c[1], mid + 1, r, p);
pushup(o);
}
ll qry(int x)
{
return t[rt[x]].val + 1ll * (x - 1) * t[rt[x]].sum;
}
int merge(int x, int y)
{
if (!x || !y)
return x | y;
int nw = x;
t[nw].c[0] = merge(t[x].c[0], t[y].c[0]);
t[nw].c[1] = merge(t[x].c[1], t[y].c[1]);
if (!t[nw].c[0] && !t[nw].c[1])
{
t[nw].val = t[x].val + t[y].val + t[y].sum * t[x].siz;
t[nw].sum = t[x].sum + t[y].sum;
t[nw].siz = t[x].siz + t[y].siz;
}
else
pushup(nw);
return nw;
}
int find(int x)
{
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
void link(int x, int y)
{
x = find(x), y = find(y);
fa[y] = x;
ans -= qry(x) + qry(y);
rt[x] = merge(rt[x], rt[y]);
ans += qry(x);
}
signed main()
{
n = read();
for (int i = 1; i <= 4e5; ++i)
fa[i] = i;
for (int i = 1; i <= n; ++i)
{
a[i] = read(), b[i] = read();
s[i] = s[i - 1] + 1ll * a[i] * b[i];
a[i] = find(a[i]), fa[a[i]] = a[i] + 1;
upd(rt[a[i]], 1, 4e5, b[i]);
}
for (int i = 1; i <= 4e5; ++i)
fa[i] = i;
for (int i = 1; i <= n; ++i)
{
ans += qry(a[i]);
if (vis[a[i] + 1])
link(a[i], a[i] + 1);
if (vis[a[i] - 1])
link(a[i] - 1, a[i]);
vis[a[i]] = 1;
write(ans - s[i]), he;
}
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18121969
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话