Codeforces Round 1031 (Div. 2) 题解

A Shashliks

您是一家广受欢迎的烤肉店的老板,您的烤架是厨房的核心。然而,烤架有一个特点:在烹饪完每一道沙司后,它的温度就会下降。

您需要烹制尽可能多的烤肉,而您有两种类型的烤肉,数量不限:

第一种类型在开始烹饪时需要至少 a 度的温度,烹饪后烤架的温度会降低 x
度。第二种在开始烹饪时要求温度至少为 b 度,烹饪后,烤架的温度会降低 y
度。
烤架的初始温度为 k 度。请确定最多可以烹制多少份烤肉。

注意烤架的温度可以是负值。

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os,  const Cont& v){
	os<<"[";
	for(auto& x:v){os<<x<<", ";}
	return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os,  const pair<Ts...>& p){
	return os<<"{"<<p.first<<", "<<p.second<<"}";
}

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		int k=read(),a=read(),b=read(),x=read(),y=read();
		if(x>y) {
			swap(x,y);swap(a,b);
		}
		ll ans=0;
		if(k>=max(a,b)) {
			ll p=(k-max(a,b))/x;
			ans+=p;
			k-=p*x;
			if(k>=max(a,b)) {
				ans++;k-=x;
			}
			
			
		}
		
		if(k>=a) {
			ll p=(k-a)/x;
			ans+=p;
			k-=p*x;
			if(k>=a) {
				ans++;k-=x;
			}
		}
		if(k>=b) {
			ll p=(k-b)/y;
			ans+=p;
			k-=p*y;
			if(k>=b) {
				ans++;k-=y;
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}


B Good Start

屋顶是一个大小为 w × h w \times h w×h 的矩形,左下角位于平面上的点 ( 0 , 0 ) (0, 0) (0,0) 。你们小组需要用大小为 a × b a \times b a×b 的相同屋顶板完全覆盖这个屋顶,条件如下:

  • 屋顶板不能旋转(甚至不能旋转 90 ∘ 90^\circ 90 )。
  • 屋顶板不能重叠(但边缘可以接触)。
  • 板材可以超出矩形屋顶的边界。

您所在小组的一名新手已经在屋顶上放置了两块这样的板材,它们没有重叠,并且每块板材部分覆盖了屋顶

你们的任务是确定是否有可能在不移除已放置的两块瓦片中任何一块的情况下完全盖住屋顶。

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os,  const Cont& v){
	os<<"[";
	for(auto& x:v){os<<x<<", ";}
	return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os,  const pair<Ts...>& p){
	return os<<"{"<<p.first<<", "<<p.second<<"}";
}

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		int w=read(),h=read(),a=read(),b=read();
		int x[2],y[2];
		Rep(i,2) x[i]=read(),y[i]=read();
		int minx=min(x[0],x[1]);
		int maxx=max(x[0],x[1]);
		if((maxx-minx)%a==0&&(x[0]!=x[1] || ((y[0]-y[1])%b==0) )) puts("YES");
		else if((y[0]-y[1])%b==0&&(y[0]!=y[1] || ((x[0]-x[1])%a==0) )) puts("YES");
		else puts("NO");
		
	}
	return 0;
}


C Smilo and Minecraft

男孩斯米罗正在玩 Minecraft!为了准备与巨龙的战斗,他需要大量的金苹果,为此,他需要大量的金币。因此,斯米罗来到了矿场。

矿洞是一个大小为 n × m n \times m n×m 的长方形网格,每个格子可以是金矿石、石头或空格子。斯米罗可以在任何空格中引爆炸药。当炸药在坐标为 ( x , y ) (x, y) (x,y) 的空格中爆炸时,以 ( x , y ) (x, y) (x,y) 格为中心、边长为 2 k + 1 2k + 1 2k+1 的正方形内的所有格子都会变成空格。如果金矿石位于这个正方形的***严格内部(不在边界上),它就会消失。但是,如果金矿石位于这个正方形的边界上,斯米罗就会收集这些金矿石。

炸药只能在矿洞内引爆,但爆炸范围可以超出矿洞边界。

确定斯米罗可以收集的最大黄金数量。

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os,  const Cont& v){
	os<<"[";
	for(auto& x:v){os<<x<<", ";}
	return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os,  const pair<Ts...>& p){
	return os<<"{"<<p.first<<", "<<p.second<<"}";
}

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
char st[600][600];
int a[600][600]={};
int s[600][600]={};
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		int n=read(),m=read(),k=read();
		For(i,n) {
			scanf("%s",st[i]+1);
			For(j,m) a[i][j]=st[i][j]=='g';
		}
		For(i,n) For(j,m) {
			s[i][j]=a[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
		}
		k--;
		int ans=1e9;
		For(i,n) For(j,m) if(st[i][j]=='.') {
			int x1=min(n,i+k);
			int y1=min(m,j+k);
			int x2=max(0,i-k-1);
			int y2=max(0,j-k-1);
			int p=s[x1][y1]-s[x1][y2]-s[x2][y1]+s[x2][y2];
			ans=min(ans,p);
		}
		cout<<s[n][m]-ans<<endl;
	}
	return 0;
}


D Cheater

您正在赌场玩一种新的纸牌游戏,游戏规则如下:

  1. 游戏使用一副由 2 n 2n 2n 张不同面值的牌组成的牌。
    1. 玩家和庄家平分这副牌:每人得到 n n n 张牌。
  2. n n n 轮游戏中,玩家和庄家同时打出手中最上面的一张牌。比较两张牌,谁的牌价值高,谁就能得分。获胜的牌将从游戏中移除,而输掉的牌将返回玩家手中,并放在其他牌的上面

请注意,游戏总是持续**** n n n 轮。

您已经跟踪了洗牌过程,并知道庄家手中牌的顺序(从上到下)。您希望最大限度地提高自己的得分,因此您可以交换手中的任意两张牌,不得超过一次(以免引起怀疑)。

确定您能获得的最高分数。


#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os,  const Cont& v){
	os<<"[";
	for(auto& x:v){os<<x<<", ";}
	return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os,  const pair<Ts...>& p){
	return os<<"{"<<p.first<<", "<<p.second<<"}";
}

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
#define MAXN (212345)
int a[MAXN],b[MAXN];
int mi[MAXN],ma[MAXN];
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		int n=read(),ans=0;
		For(i,n) a[i]=read();
		For(i,n) b[i]=read();
		Fork(i,2,n) b[i]=min(b[i],b[i-1]);
		
//		mi[1]=a[1];
//		Fork(i,2,n) mi[i]=min(a[i],mi[i-1]);
		ma[n]=a[n];
		ma[n+1]=0;
		ForD(i,n-1) ma[i]=max(a[i],ma[i+1]);
		multiset<int> S;
		For(i,n) {
			S.insert(a[i]);
			if(S.size()==1) {
				auto it=S.begin();
				int p1=*it;
				p1=max(p1,ma[i+1]);
				int q=p1;
				if(q>b[n-i+1]) ans=i;
				continue;
			}
			auto it=S.begin();
			int p1=*it;
			++it; int p2=*it;
			p1=max(p1,ma[i+1]);
			int q=min(p1,p2);
			if(q>b[n-i+1]) ans=i;
		}
		
		cout<<ans<<endl;
	}
	return 0;
}


E From Kazan with Love

马拉是喀山人。喀山可以表示为一棵由 n n n 个顶点组成的无向树。马拉特年轻时经常在街头打架,现在他在喀山有 m m m 个敌人,编号从 1 1 1 m m m

每天,住在城里的所有人都要去上班。马拉特知道,他的 i i i 个敌人住在顶点 a i a_i ai ,在顶点 b i b_i bi 工作。他自己生活在顶点 x x x ,工作在顶点 y y y 。可以保证 a i ≠ x a_i \ne x ai=x .

所有敌人都通过最短路径上班,并在 1 1 1 时刻离开家。也就是说,如果我们将顶点 a i a_i ai b i b_i bi 之间的最短路径表示为 c 1 , c 2 , c 3 , … , c k c_1, c_2, c_3, \ldots, c_k c1,c2,c3,,ck (其中 c 1 = a i c_1 = a_i c1=ai c k = b i c_k = b_i ck=bi ),那么在 p p p 1 ≤ p ≤ k 1 \le p \le k 1pk )时刻,编号为 i i i 的敌人将在顶点 c p c_p cp 处。

马拉特确实不希望同时在同一顶点遇到任何敌人,因为这会造成尴尬的局面,但他们可以在边缘相遇。马拉特也在时间 1 1 1 离开了他的家,在随后的每个时间点,他都可以移动到相邻的顶点或停留在当前顶点。

请注意,马拉特只能在 2 , 3 , … , k 2, 3, \ldots, k 2,3,,k 时刻(其中 c 1 , c 2 , … , c k c_1, c_2, \ldots, c_k c1,c2,,ck 是顶点 a i a_i ai b i b_i bi 之间的最短路径)遇到 i i i /-th敌人。换句话说,从敌人到达工作地点的那一刻起,马拉就不能再与他相遇了。

请帮助马拉特找到在不遇到任何敌人的情况下到达工作地点的最早时刻,或者确定这是不可能的。

马拉是喀山人。喀山可以表示为一棵由 n n n 个顶点组成的无向树。马拉特年轻时经常在街头打架,现在他有 m m m 个敌人,从 1 1 1 m m m ,和他一起生活在喀山。每天,住在城里的所有人都要去上班。马拉特知道,他的敌人的 i i i ()住在顶点 a _ i a\_i a_i ,在顶点 b _ i b\_i b_i 工作。他自己住在顶点 x x x ,工作在顶点 y y y 。保证 a _ i n e x a\_i \\ne x a_inex 。所有敌人都通过最短路径上班,并在时间 1 1 1 离开家。也就是说,如果我们把顶点 a _ i a\_i a_i b _ i b\_i b_i 之间的最短路径表示为 c _ 1 , c _ 2 , c _ 3 , l d o t s , c _ k c\_1, c\_2, c\_3, \\ldots, c\_k c_1,c_2,c_3,ldots,c_k (其中 c _ 1 = a _ i c\_1 = a\_i c_1=a_i c _ k = b _ i c\_k = b\_i c_k=b_i ),那么在 p p p 1 l e p l e k 1 \\le p \\le k 1leplek )时刻,编号为 i i i 的敌人将出现在顶点 c _ p c\_p c_p 。马拉特真的不想同时在同一个顶点遇到他的敌人,因为这会造成尴尬的局面,但是他们可以在边缘相遇。马拉特也在时间 1 1 1 离开了他的家,在随后的每个时间点,他都可以移动到相邻的顶点或留在当前的顶点。请注意,马拉特只能在 2 , 3 , l d o t s , k 2, 3, \\ldots, k 2,3,ldots,k 时刻(其中 c _ 1 , c _ 2 , l d o t s , c _ k c\_1, c\_2, \\ldots, c\_k c_1,c_2,ldots,c_k 是顶点 a _ i a\_i a_i b _ i b\_i b_i 之间的最短路径)与 i i i /th敌人相遇。换句话说,从敌人到达工作地点的那一刻起,马拉就再也见不到他了。帮助马拉特找到他可以在不遇到任何敌人的情况下到达工作地点的最早时间点,或者确定这是不可能的。

动态维护当前合法位置和新加入的位置,下一个新加入位置的集合=(当前新加入位置的集合的邻域+本回合被ban的点)交(当前合法位置的邻域)。

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

//#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os,  const Cont& v){
	os<<"[";
	for(auto& x:v){os<<x<<", ";}
	return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os,  const pair<Ts...>& p){
	return os<<"{"<<p.first<<", "<<p.second<<"}";
}

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
#define MAXN (212345)
int f[MAXN],dep[MAXN],n,m,x,y;
vi v[MAXN];

void dfs(int x,int fa,int d) {
	ll restot=0;
	f[x]=fa;dep[x]=d;
	for (auto u:v[x])
		if (u!=fa) {
			dfs(u,x,d+1);
	}
}
vi get_path(int x,int y) {
	vi g,rg;
	while(x^y) {
		if(dep[x]>dep[y]) g.pb(x),x=f[x];
		else if(dep[x]<dep[y]) rg.pb(y),y=f[y];
		else g.pb(x),x=f[x],rg.pb(y),y=f[y];
	}
	g.pb(x);
	reverse(ALL(rg));
	move(ALL(rg), back_inserter(g));
	return g;
	
}
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		n=read(),m=read(),x=read(),y=read();
		For(i,n-1) {
			int x=read(),y=read();
			v[x].pb(y); v[y].pb(x);
		}
		dfs(1,-1,0);
		vector<vector<int> > path;
		vector<vector<int> > t_ban(2*n+2,vector<int>{});
		Rep(i,m) {
			int x=read(),y=read();
			path.pb(get_path(x,y));
			int sz=SI(path[i]);
			Rep(j,sz) t_ban[j].pb(path[i][j]);
		}
		
		vector<int> nx,tmp;
		for(auto p:v[x]) nx.pb(p);
		vector<int> b(n+1,0),vis(n+1,0),tmpvis(n+1,0);
		b[x]=1;
		For(i,2*n+1) {
			for(int j:t_ban[i]) vis[j]=i;
			
			for(int j:nx) b[j]=1;
			for(int j:t_ban[i]) b[j]=0;
			
			for(int j:t_ban[i]) {
				bool fl=0;
				for(int k:v[j]) if(b[k]) {fl=1;break;}
				if(!fl) continue;
				if(tmpvis[j]!=i) tmpvis[j]=i,tmp.pb(j);
			}
			for(int j:nx) if(b[j]) {
				for(int k:v[j]) if(!b[k] && tmpvis[k]!=i) tmpvis[k]=i,tmp.pb(k);
			}
			swap(tmp,nx);
			tmp.resize(0);
			if(b[y]) {
				cout<<i+1<<endl;break;
			}
		}
		if(!b[y]) cout<<-1<<endl;
		
		For(i,n) v[i].resize(0);
	}
	return 0;
}


F Two Arrays

给你两个长度为 n n n 的数组 a a a b b b 。您可以无限次地执行以下操作:

  • 1 1 1 n n n 中选择一个整数 i i i 并交换 a i a_i ai b i b_i bi

f ( c ) f(c) f(c) 是数组 c c c 中不同数字的个数。求 f ( a ) + f ( b ) f(a) + f(b) f(a)+f(b) 的最大值。同时,输出执行所有操作后的数组 a a a b b b

#include<bits/stdc++.h> 
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForkD(i,k,n) for(int i=n;i>=k;i--)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  
#define Lson (o<<1)
#define Rson ((o<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,0x3f,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define MEMx(a,b) memset(a,b,sizeof(a));
#define INF (0x3f3f3f3f)
#define F (1000000007)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define vi vector<int> 
#define pi pair<int,int>
#define SI(a) ((a).size())
#define Pr(kcase,ans) printf("Case #%d: %lld\n",kcase,ans);
#define PRi(a,n) For(i,n-1) cout<<a[i]<<' '; cout<<a[n]<<endl;
#define PRi2D(a,n,m) For(i,n) { \
						For(j,m-1) cout<<a[i][j]<<' ';\
						cout<<a[i][m]<<endl; \
						} 
#pragma comment(linker, "/STACK:102400000,102400000")
#define ALL(x) (x).begin(),(x).end()
#define gmax(a,b) a=max(a,b);
#define gmin(a,b) a=min(a,b);
#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#define DEBUG
int recur_depth = 0;
#ifdef DEBUG
#define dbg(x) {++recur_depth; auto x_=x; --recur_depth; cerr<<string(recur_depth, '\t')<<"\e[91m"<<__func__<<":"<<__LINE__<<"\t"<<#x<<" = "<<x_<<"\e[39m"<<endl;}
#else
#define dbg(x)
#endif
template<typename Ostream, typename Cont>
typename enable_if<is_same<Ostream,ostream>::value, Ostream&>::type operator<<(Ostream& os,  const Cont& v){
	os<<"[";
	for(auto& x:v){os<<x<<", ";}
	return os<<"]";
}
template<typename Ostream, typename ...Ts>
Ostream& operator<<(Ostream& os,  const pair<Ts...>& p){
	return os<<"{"<<p.first<<", "<<p.second<<"}";
}

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return ((a-b)%F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
	while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
	return x*f;
} 
#define MAXN (212345)
int b[MAXN],a[MAXN];
vector<pair<int,int> >  v[MAXN];
int an1[MAXN],an2[MAXN];
bool vis[MAXN]={};
bool vis2[MAXN]={};
bool is_c[MAXN]={};
void dfs2(int x,int fa,int faid) {
	vis2[x]=1;
	for (auto u:v[x])
		if (!vis2[u.fi]) {
			dfs2(u.fi,x,u.se);
		}else if(faid!=u.se) {
			is_c[x]=1;
		}
}
void dfs(int x,int fa) {
	vis[x]=1;
	for (auto u:v[x])
		if (!vis[u.fi]) {
			an1[u.se]=x;
			an2[u.se]=u.fi;
			dfs(u.fi,x);
		}else if(!an1[u.se]) {
			an1[u.se]=x;
			an2[u.se]=u.fi;
		}
}
int main()
{
//	freopen("A.in","r",stdin);
//	freopen(".out","w",stdout);
	int T=read();
	while(T--) {
		int n=read();
		vi deg(2*n+1,0);
		For(i,n) a[i]=read();
		For(i,n) b[i]=read();
		For(i,2*n) an1[i]=an2[i]=vis[i]=vis2[i]=is_c[i]=0;
		For(i,n) {
			int x=a[i],y=b[i];
			v[x].pb(mp(y,i)); v[y].pb(mp(x,i));
			deg[x]++,deg[y]++;
		}
		For(i,2*n) if(!vis[i] && deg[i]==1)dfs(i,-1);
		For(i,2*n) if(!vis2[i] &&!vis[i] && deg[i]>1) dfs2(i,-1,-1);
		For(i,2*n) if(!vis[i] && deg[i]>1 && is_c[i]) {
			dfs(i,-1);
		}
		int ans=0;
		For(i,2*n) if(deg[i]==1) ans++;
		else if(deg[i]>1) ans+=2;	
		cout<<ans<<endl;	

		PRi(an1,n)
		PRi(an2,n)
		
		For(i,2*n) v[i].resize(0);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值