博主的 BiBi 时间
今天考试全线炸裂。这道 (T1) 连电风扇的分都没拿到。(我竟然还专门思考了一波不用线段树 (QwQ))
Solution
我们可以把 ([l,r]) 的翻转看作差分:把 (l) 加一,把 (r+1) 加一(注意这是在模二意义下的)。
设 (l_i,r_i) 分别为第 (i) 段的起点与终点。最后我们要求将 (val[l_2]==val[r_2+1]==val[l_4]==val[r_4+1]==1)(注意这是在模二意义下的)。
我们可以把这个玩意转化成图论问题:从某个起点(例如 (l_2))出发,经过某几条边到达终点(例如 (r_2+1))。
可以证明这个方法的正确性:假设有 (i<j<k),有 (edge(i,k)) 到 (edge(k,j)),其实就是 (i->j) 也就是操作两个区间,向其他方向的同理。
我们有三种方法达到目的(注意之后的 (a,b,c,d,e) 都已经是代表下标了):
100111000011111
a b c d e
- ([a+1,b+1],[c+1,d+1])
- ([a+1,c+1],[b+1,d+1])
- ([a+1,d+1],[b+1,c+1])
注意 (Dijkstra) 里面的 (vis[s]) 不要赋值,会错。
Code
#include <queue>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
const ll inf = 1e18;
int n, a[10], nxt[N << 1], to[N << 1], head[N * 5], cnt;
ll ans = inf, dis[N * 5], w[N << 1];
bool vis[N * 5];
struct node {
ll w; int id;
node() {}
node(const ll W, const int Id) {w = W; id = Id;}
bool operator < (const node x) const {
return w > x.w;
}
};
priority_queue <node> q;
int read() {
int x = 0, f = 1; char s;
while((s = getchar()) > '9' || s < '0') if(s == '-') f = -1;
while(s <= '9' && s >= '0') x = (x << 1) + (x << 3) + (s ^ 48), s = getchar();
return x * f;
}
void addEdge(const int u, const int v, const ll val) {
nxt[++ cnt] = head[u], to[cnt] = v, w[cnt] = val, head[u] = cnt;
}
ll Dijkstra(const int s, const int t) {
for(int i = 1; i <= a[5] + 1; ++ i) dis[i] = inf, vis[i] = 0;
dis[s] = 0;
q.push(node(0, s));
while(! q.empty()) {
int u = q.top().id; q.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; i; i = nxt[i])
if(dis[to[i]] > dis[u] + w[i]) dis[to[i]] = dis[u] + w[i], q.push(node(dis[to[i]], to[i]));
}
return dis[t] == inf ? -1 : dis[t];
}
int main() {
int u, v; ll r1, r2;
for(int i = 1; i <= 5; ++ i) a[i] = read() + a[i - 1];
n = read();
for(int i = 1; i <= n; ++ i) {
u = read(), v = read();
addEdge(u, v + 1, v - u + 1), addEdge(v + 1, u, v - u + 1);
}
r1 = Dijkstra(a[1] + 1, a[2] + 1), r2 = Dijkstra(a[3] + 1, a[4] + 1);
if(r1 != -1 && r2 != -1) ans = min(ans, r1 + r2);
r1 = Dijkstra(a[1] + 1, a[3] + 1), r2 = Dijkstra(a[2] + 1, a[4] + 1);
if(r1 != -1 && r2 != -1) ans = min(ans, r1 + r2);
r1 = Dijkstra(a[1] + 1, a[4] + 1), r2 = Dijkstra(a[2] + 1, a[3] + 1);
if(r1 != -1 && r2 != -1) ans = min(ans, r1 + r2);
printf("%lld
", ans == inf ? -1 : ans);
return 0;
}