Codeforces 516E - Drazil and His Happy Friends(同余最短路)

Codeforces 题面传送门 & 洛谷题面传送门

首先思考一个非常简单的性质:记 \(d=\gcd(n,m)\),那么每次在一起吃完饭的男女孩编号必定与 \(d\) 同余,而根据斐蜀定理可以得到另一方面的结论:对于每一个 \(\bmod d\) 的剩余类,如果其中至少有一个男孩/女孩是快乐的,那所有与这样的男孩/女孩编号 \(\bmod d\) 同余的男孩/女孩最终都会变得快乐。

这样 \(-1\) 的情况就很好判断了:只要检查每个 \(\bmod d\) 的剩余类都至少有一个男孩/女孩是快乐的即可,特别地,如果 \(d>b+g\) 那答案肯定是 \(-1\),而显然要解决答案不是 \(-1\) 的情况,只需要对每个 \(\bmod d\) 的剩余类 \(x\) 都做一遍 \(n,m\) 的互质的情况,设其答案为 \(ans\),然后令答案对 \(ans\times d+x\)\(\max\) 即可。

考虑如何解决 \(n,m\) 互质的情况,考虑同余最短路(怎么想到的/bx,实是神仙),我们考虑这样建图:

  • 对于每个快乐的男孩 \(b\),连一条 \(S\to b\),权值为 \(b\) 的边。
  • 对于每个快乐的女孩 \(g\),连一条 \(S\to g\bmod n\),权值为 \(g\) 的边,表示这个女孩 \(g\) 最早会在 \(g\) 时刻带动男孩 \(g\bmod n\) 变得快乐。
  • 对于每个男孩 \(i\),连边 \(i\to(i+m)\bmod n\),权值为 \(m\),表示如果 \(i\) 变得快乐,那么 \(m\) 时间以后 \((i+m)\bmod n\) 也会变得快乐。

跑最短路即可,最后我们取源点到所有一开始不快乐的男孩距离的最大值,就是所有男孩变得快乐的时间的最大值,然后再对所有女孩做一遍同样的操作即可。

直接建图跑 dijkstra 复杂度是 \(n\log n\) 的,无法通过。我们发现第三类边构成了一个环,因此这个模型可以视作一个环上加了一些源点连到环上某个点的边,要求源点到所有非关键点的距离最大值,而关键点个数很小,因此我们考虑将关键点压进一个 set,然后对于两个相邻关键点 \(l,r\) 路径上的所有点,显然到源点距离最大的肯定是 \(r-1\),因此我们 \(\mathcal O(k)\) 地算出所有这样的 \(r-1\) 到源点的距离,然后取 \(\max\) 即可,这样复杂度就降到了 \(k\log k\),其中 \(k\) 为关键点个数。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
#define mt make_tuple
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long double ld;
namespace fastio{
	#define FILE_SIZE 1<<23
	char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
	inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
	inline void putc(char x){(*p3++=x);}
	template<typename T> void read(T &x){
		x=0;char c=getchar();T neg=0;
		while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
		while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
		if(neg) x=(~x)+1;
	}
	template<typename T> void recursive_print(T x){return (!x)?void():(recursive_print(x/10),putc(x%10^48),void());}
	template<typename T> void print(T x){(!x)&&(putc('0'),0);(x<0)&&(putc('-'),x=~x+1);recursive_print(x);}
	template<typename T> void print(T x,char c){print(x);putc(c);}
	void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e5;
const ll INFll=0x3f3f3f3f3f3f3f3fll;
int n,m,B,G,N,M;
vector<int> b[MAXN+5],g[MAXN+5];
int gcd(int x,int y){return (!y)?x:gcd(y,x%y);}
void exgcd(int x,int y,int &a,int &b){
	if(!y) return a=1,b=0,void();exgcd(y,x%y,a,b);
	int tmp=a;a=b;b=tmp-(x/y)*b;
}
int getinv(int a,int mod){
	int x,y;exgcd(a,mod,x,y);
	return (x+mod)%mod;
}
ll solve(vector<int> &b,vector<int> &g,int n,int m){
	map<int,bool> in;map<int,int> dis;set<int> pos;
	for(int x:b){in[x]=1;pos.insert(x);dis[x]=x;}
	for(int x:g){
		pos.insert(x%n);
		if(!dis.count(x%n)) dis[x%n]=x%n;
		else chkmin(dis[x%n],x%n);
	} int iv=getinv(m,n);
	vector<pair<int,pii> > vec;int pos0=(*pos.begin());
	for(int p:pos) vec.pb(mp(1ll*(p-pos0)*iv%n,mp(dis[p],in[p])));
	vec.pb(mp(n,mp(0,1)));sort(vec.begin(),vec.end());ll mx=-1;
//	for(int i=0;i<vec.size();i++) printf("%d %d %d\n",vec[i].fi,vec[i].se.fi,vec[i].se.se);
//	printf("\n");
	for(int i=1;i<vec.size();i++) if(!vec[i-1].se.se||vec[i].fi!=vec[i-1].fi+1)
		chkmax(mx,1ll*(vec[i].fi-vec[i-1].fi-1)*m+vec[i-1].se.fi);
//	printf("%d\n",mx);
	return mx;
}
int main(){
	scanf("%d%d",&n,&m);int d=gcd(n,m);N=n/d;M=m/d;
	if(d>MAXN) return puts("-1"),0;
	scanf("%d",&B);for(int i=1,x;i<=B;i++) scanf("%d",&x),b[x%d].pb(x/d);
	scanf("%d",&G);for(int i=1,x;i<=G;i++) scanf("%d",&x),g[x%d].pb(x/d);
	for(int i=0;i<d;i++) if(b[i].empty()&&g[i].empty()) return puts("-1"),0;
	ll res=0;
	for(int i=0;i<d;i++){
		chkmax(res,1ll*d*solve(b[i],g[i],N,M)+i);
		chkmax(res,1ll*d*solve(g[i],b[i],M,N)+i);
	} printf("%lld\n",res);
	return 0;
}
posted @ 2021-11-03 14:55  tzc_wk  阅读(103)  评论(0编辑  收藏  举报