Educational Codeforces Round 172 (Rated for Div. 2) D. Recommendations
算法#
听别人说这题比较简单, 我来看看怎么个事
转化题意,
对于
显然的,
那么我们考虑将每一条线段当做一个点处理, 放到以
这下变成板子题了, 那么我们去学新算法吧
关于二维数点 & 扫描线#
扫描线实际上就是暴力枚举一维, 另一维用数据结构维护, 以此来做到优化时间复杂度
但是二维数点这种问题怎么办?
我们考虑离线询问, 按照一维排序, 那么对于另一个维度, 树状数组区间和即可
那么对于这道题, 我们怎么去处理
首先假设按照
代码#
#include <bits/stdc++.h>
using namespace std;
const int m = 1e9 + 2;
int n, s[200005];
struct su
{
int x, y, id;
bool operator<(const su &temp) const
{
if (x == temp.x)
return y > temp.y;
return x < temp.x;
}
} a[200005];
int ans[200005];
void add(int x, int v)
{
for (; x <= n; x += x & -x)
s[x] = max(s[x], v);
}
int ask(int x)
{
int res = 0;
for (; x; x -= x & -x)
res = max(s[x], res);
return res;
}
void solve()
{
cin >> n;
set<int> q;
vector<int> f;
unordered_map<int, int> mp;
for (int i = 1; i <= n; ++i)
{
int x, y;
cin >> x >> y;
a[i].x = x;
a[i].y = y;
a[i].id = i;
f.push_back(a[i].y); // 按照 x 进行一个扫, 把 y 加入
s[i] = 0;
}
sort(f.begin(), f.end());
reverse(f.begin(), f.end());
unique(f.begin(), f.end());
for (int i = 0; i < f.size(); ++i) // 离散化
mp[f[i]] = i + 1;
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++)
{
if (i > 1)
{
q.insert(a[i - 1].y);
add(mp[a[i - 1].y], a[i - 1].x);
}
if (i < n && a[i].x == a[i + 1].x && a[i].y == a[i + 1].y)
{
ans[a[i].id] = 0;
continue;
}
auto xx = q.lower_bound(a[i].y);
if (xx == q.end())
{
ans[a[i].id] = 0;
continue;
}
int y = ask(mp[a[i].y]);
if ((*xx) < y)
{
ans[a[i].id] = 0;
continue;
}
ans[a[i].id] = (*xx) - y - (a[i].y - a[i].x);
}
for (int i = 1; i <= n; i++)
{
cout << ans[i] << "\n";
}
}
int main()
{
int t;
cin >> t;
while (t--)
solve();
}
总结#
善于转化问题
注意问题到底需要求最值的哪边
vivo 50
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】