HDU 7391 Solution
题面
思路
差分。
直接使用 map
在原坐标轴上维护关于不同坐标上买到所有种类的最小距离差分数组。
差分值只会在拥有相同种类商品的中点处发生变化。
举个例子。
以 *
指代商品。
距离为
3 2 1 * 1 2 1 * 1 2 2 1 * 1 2 3
对应差分数组为
3 -1 -1 -1 1 1 -1 -1 1 1 0 -1 -1 1 1 1
对应二维差分数组为
3 -4 0 0 2 0 -2 0 2 0 -1 -1 0 2 0 0
可见,当两个商品坐标差为偶数时,距离会突然折返;而坐标差为奇数时,距离会先变得相同后减少。
多层商品叠加处理方法相同。
代码
#include <iostream>
#include <map>
#include <vector>
using namespace std;
const int N = 5e5 + 10;
int n, c, prv[N];
using ll = long long;
ll curp, curv, curd, mn;
map<int, vector<int>> mp;
map<int, int> ad;
void run()
{
mn = 1e18;
ad.clear();
mp.clear();
curd = 0;
curp = -1;
curv = 0;
scanf("%d%d", &n, &c);
ad[0] = -c;
for (int i = 1; i <= c; i++)
prv[i] = 0;
for (int i = 1, r, t; i <= n; i++)
{
scanf("%d%d", &r, &t);
for (int j = 1, x; j <= t; j++)
{
scanf("%d", &x);
mp[r].push_back(x);
}
}
for (auto &[k, v] : mp)
{
for (auto &j : v)
{
if (prv[j])
{
if ((k - prv[j]) & 1 ^ 1)
{
ad[((k + prv[j]) >> 1) + 1] -= 2;
}
else
{
ad[((k + prv[j]) >> 1) + 1]--;
ad[((k + prv[j]) >> 1) + 2]--;
}
}
else
{
curv += k + 1;
}
ad[k + 1] += 2;
prv[j] = k;
}
}
for (auto &[k, v] : ad)
{
curv += curd * (k - 1 - curp);
mn = min(mn, curv);
curp = k - 1;
// printf("%lld %lld\n", curp, curv);
curd += v;
}
printf("%lld\n", mn);
}
int main()
{
int T = 1;
scanf("%d", &T);
while (T--)
run();
}