「JOISC 2015 Day 1」卡片占卜
「JOISC 2015 Day 1」卡片占卜
序列:\(1_10_21_30_41_5\)
要求令\(0_2,0_4\)取反为\(1_2,1_4\)
考虑将每次操作\([l,r ]\)转化为一条连接\(l\)和\(r+1\)边(\(r+1\)点并未被反转)(双向边)。
假如要反转一个区间\([l,r]\),考虑\(l\)到\(r+1\)的路径的效果:按照经过边对应的操作,必然只会取反\([l,r]\)区间,即仅有\([l,r ]\)区间的点被经过奇数次。
证明:
-
如果没有向左走,那么显然正确。
- 如果向左走边\(r_1->l_1\),那么\([l1,r1-1]\)反转了偶数次(无效),总体相当于反转\([l,l_1-1]\)区间。
因此反转一个指定区间所花费的最短时间可以通过一次\(dijkstra\)求出。
反转$1_2,1_4 $的方案共三种:
- 反转\(0_2,0_4\)
- 反转\(0_21_30_4,1_3\)
- 反转\(0_21_3,1_30_4\)
#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
void in(int &r) {
static char c;
r=0;
while(c=getchar(),!isdigit(c));
do r=(r<<1)+(r<<3)+(c^48);
while(c=getchar(),isdigit(c));
}
const int mn=500005;
int head[mn],ne[200005],to[200005],cnt1,cost[200005];
#define link(a,b,c) link_edge(a,b,c),link_edge(b,a,c)
#define link_edge(a,b,c) to[++cnt1]=b,ne[cnt1]=head[a],head[a]=cnt1,cost[cnt1]=c
#define travel(x) for(int q(head[x]);q;q=ne[q])
struct node{
long long v;
int id;
bool operator <(const node &A)const{
return v>A.v;
}
};
priority_queue<node> qw;
const long long INF=1e18;
long long d[mn];
int n,td;
bool mark[mn];
long long dijkstra(int s,int t){
rep(q,1,td+1)d[q]=INF,mark[q]=0;
while(!qw.empty())qw.pop();
d[s]=0;
qw.push({d[s],s});
while(!qw.empty()){
int now=qw.top().id;
qw.pop();
if(mark[now])continue;
mark[now]=1;
travel(now)if(d[to[q]]>d[now]+cost[q]){
d[to[q]]=d[now]+cost[q];
qw.push({d[to[q]],to[q]});
}
}
if(d[t]==INF)return -1;
return d[t];
}
int main(){
int a,b,c,d,e;
in(a),in(b),in(c),in(d),in(e);
b+=a,c+=b,d+=c,e+=d;
td=e;
int x,y;
in(n);
rep(q,1,n)in(x),in(y),link(x,y+1,abs(y-x)+1);
long long ans=INF,v1,v2;
v1=dijkstra(a+1,b+1),v2=dijkstra(c+1,d+1);
if(v1!=-1&&v2!=-1)ans=min(ans,v1+v2);
v1=dijkstra(a+1,d+1),v2=dijkstra(b+1,c+1);
if(v1!=-1&&v2!=-1)ans=min(ans,v1+v2);
v1=dijkstra(a+1,c+1),v2=dijkstra(b+1,d+1);
if(v1!=-1&&v2!=-1)ans=min(ans,v1+v2);
if(ans==INF)ans=-1;
printf("%lld\n",ans);
return 0;
}