AT1252 IOIOI カード占い
AT1252 IOIOI カード占い
记原数组为 数组。
差分,转化为一堆 和 个 。
每次区间翻转操作即翻转差分数组两点。
答案即翻转 个 的最小操作数,转化为操作任意两点和操作另外两次两次操作。
以每个 点为起点跑最短路即可,一条路径对应翻转两点。
时间复杂度 。
#include<bits/stdc++.h>
using namespace std;
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 << 3) + (x << 1) + (c ^ 48), 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 + 48);
}
const int _ = 5e5 + 10;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n, a[6];
bool vis[_];
ll dis[3][_], ans = inf;
vector<ll> d[_], w[_];
void dij(int s, ll *di)
{
memset(vis, 0, sizeof vis);
priority_queue<pair<ll, int>> q;
q.push({0, s});
di[s] = 0;
while(!q.empty())
{
int u = q.top().second;
q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = 0; i < d[u].size(); ++i)
{
int v = d[u][i];
if(di[v] > di[u] + w[u][i])
{
di[v] = di[u] + w[u][i];
if(!vis[v]) q.push({-di[v], v});
}
}
}
}
signed main()
{
memset(dis, inf, sizeof dis);
for(int i = 1; i <= 5; ++i) a[i] = read() + a[i - 1];
n = read();
for(int i = 1, u, v; i <= n; ++i)
{
u = read(), v = read();
d[u].push_back(v + 1), d[v + 1].push_back(u);
w[u].push_back(v - u + 1), w[v + 1].push_back(v - u + 1);
}
dij(a[1] + 1, dis[0]), dij(a[2] + 1, dis[1]), dij(a[3] + 1, dis[2]);
ans = min(ans, dis[0][a[2] + 1] + dis[2][a[4] + 1]);
ans = min(ans, dis[0][a[3] + 1] + dis[1][a[4] + 1]);
ans = min(ans, dis[0][a[4] + 1] + dis[1][a[3] + 1]);
write(ans == inf ? -1 : ans), he;
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18121960