[AT1252] IOIOI カード占い
前言
考场上想出\(\text{Dijkstra}\)的是魔鬼吧
毫无防备地流下了属于真正弱者的泪水.jpg
题目
讲解
所有的 I 被我换成了\(1\),而 O 换成了\(0\)
暴力
从考场思路开始吧
首先有显而易见的结论:
1.选择的操作顺序不影响答案
2.每个操作重复做没有意义
好了,这就是我们暴力的基础
\(2^n\)枚举操作,判断是否成立,取时间最小值即可
我是用\(bitset\)实现的,这里代码就不给出了
正解
差分 & 最短路
区间修改?好难啊! -> 差分!单点修改
如果当前点和前一个点不一样,取\(1\),反之取\(0\)
如样例可这样变化:
\(100111000011111\)
\(010100100010000\)
现在我们只需将所有的\(1\)改为\(0\)即可
上面所对应的\(1\)的位置为:
A+1 , A+B+1 , A+B+C+1 , A+B+C+D+1
由于差分后变为单点修改,那么我们的修改操作也变为了两个点的单点修改
即\(u,v\)的区间修改变为了\(u,v+1\)的单点修改
记上面对应的\(1\)的位置为\(a,b,c,d\)
我们就有三个修改方案:\(ab\ \&\ cd\ ,\ ac\ \&\ bd\ ,\ ad\ \&\ bc\)
而修改两个点的最小代价就可以用最短路算法\(\text{dijkstra}\)求得
由于起点只有\(a,b,c\)三个点,所以我们需要跑三次\(\text{dijkstra}\)
最后答案取最小值就好了
坑点
-
注意开\(\text{long long}\)
-
空间要开\(5e5\)而非\(1e5\)
-
答案输出要换行! (\(\text{AT}\)老题特性)
代码
//12252024832524
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 500005;
const LL INF = 0x3f3f3f3f3f3f3f3f;
int n,init[6];
LL dis[3][MAXN],ans = INF;
struct node
{
int x;
LL d;
node(){}
node(int x1,LL d1){
x = x1;
d = d1;
}
bool operator < (const node &px) const{
return d >= px.d;
}
};
int Read()
{
int x = 0,f = 1;char c = getchar();
while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
return x * f;
}
void Put1(LL x)
{
if(x > 9) Put1(x/10);
putchar(x%10^48);
}
void Put(LL x,char c = -1)
{
if(x < 0) putchar('-'),x = -x;
Put1(x);
if(c >= 0) putchar(c);
}
template <typename T>T Max(T x,T y){return x > y ? x : y;}
template <typename T>T Min(T x,T y){return x < y ? x : y;}
template <typename T>T Abs(T x){return x < 0 ? -x : x;}
int head[MAXN],tot;
struct edge
{
int v,val,nxt;
}e[MAXN << 1];
void Add_Edge(int x,int y,int z)
{
e[++tot].v = y;
e[tot].val = z;
e[tot].nxt = head[x];
head[x] = tot;
}
void Add_Double_Edge(int x,int y,int z)
{
Add_Edge(x,y,z);
Add_Edge(y,x,z);
}
void dij(int s,LL *DIS)
{
priority_queue<node> q;
q.push(node(s,0));
DIS[s] = 0;
while(!q.empty())
{
node t = q.top();
q.pop();
if(t.d > DIS[t.x]) continue;
for(int i = head[t.x]; i ;i = e[i].nxt)
{
if(DIS[e[i].v] > DIS[t.x] + e[i].val)
{
DIS[e[i].v] = DIS[t.x] + e[i].val;
q.push(node(e[i].v,DIS[e[i].v]));
}
}
}
}
int main()
{
// freopen("cards.in","r",stdin);
// freopen("cards.out","w",stdout);
memset(dis,INF,sizeof(dis));
for(int i = 1;i <= 5;++ i) init[i] = Read() + init[i-1];
n = Read();
for(int i = 1,u,v;i <= n;++ i) u = Read(),v = Read(),Add_Double_Edge(u,v+1,v-u+1);
dij(init[1]+1,dis[0]);//A
dij(init[2]+1,dis[1]);//B
dij(init[3]+1,dis[2]);//C
ans = Min(ans,dis[0][init[2]+1] + dis[2][init[4]+1]);//AB & CD
ans = Min(ans,dis[0][init[3]+1] + dis[1][init[4]+1]);//AC & BD
ans = Min(ans,dis[0][init[4]+1] + dis[1][init[3]+1]);//AD & BC
if(ans == INF) Put(-1,'\n');
else Put(ans,'\n');
return 0;
}