codeforces Round 875 div2

# codeforces Round 875 div2

A. Twin Permutations

题意:

给一个permutation类数组(即长度为n的数组,必须1~n都存在) a ,让找到一个相同长度的 数组 b,使得 a i + b i ≤ a i + 1 + b i + 1 a_i+b_i \leq a_{i+1}+b_{i+1} ai+biai+1+bi+1

思路:

和等差数列一样 a 1 + a n = a 2 + a n − 1 a_1+a_n=a_2+a_{n-1} a1+an=a2+an1, 即每个数都有一个配对的数可以使得他们加起来相等;

代码

void solve()
{
	cin>>n;
	int x;
	for(int i=1;i<=n;i++) {cin>>x;cout<<n+1-x<<" "};
	cout<<endl;
}

B. Array merging

题意

两个数组,找合在一起后最长的相同元素的子串。合的过程是从 a,b数组一个一个拿下来;

思路:

两个数组中相同的元素的长度加起来求max

代码:

int n,m,k,_;
int a[N*2],b[N*2];
int cnt1[N*2],cnt2[N*2];
map<int,int>mp;
void solve()
{
	cin>>n;
	for(int i=1;i<=n*2;i++)
		cnt1[i]=cnt2[i]=0;

	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	for(int i=1;i<=n;i++)
		cin>>b[i];
	for(int i=1;i<=n;)
	{
		int j=i+1;
		while(a[j]==a[i]&&j<=n) j++;
		cnt1[a[i]]=max(cnt1[a[i]],j-i);
		i=j;
	}
	int mx=0;
	
	for(int i=1;i<=n;)
	{
		int j=i+1;
		while(b[j]==b[i]&&j<=n) j++;
		cnt2[b[i]]=max(cnt2[b[i]],j-i);
		i=j;
		
	}
	for(int i=1;i<=2*n;i++)
		mx=max(cnt1[i]+cnt2[i],mx);
	cout<<mx<<endl;
	
}

C. Copil Copac Draws Trees

思路:

记一下边的序号再dfs

代码

vector<int>e[N];
bool vis[N];
map<PII,int>mp;
int dfs(int p,int s)
{
	int ans=0;
	for(auto u:e[s])
		ans=max(ans,dfs(s,u)+(mp[{p,s}]<mp[{s,u}]));
	return ans;
}
void solve()
{
	cin>>n;
	memset(vis,0,sizeof vis);
	for(int i=1;i<n;i++)
	{
		int u,v;
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
		mp[{u,v}]=i;
		mp[{v,u}]=i;
	}
	int ans=0;
	for(auto p:e[1]) ans=max(ans,dfs(1,p));
		cout<<ans<<endl;
}

D. The BOSS Can Count Pairs

题意:

给长度为n、范围为1~n的两个数组ab, 求有多少组 a i ∗ a j = b i + b j a_i * a_j = b_i + b_j aiaj=bi+bj , 1 ≤ n ≤ 2 × 1 0 5 1 \leq n \leq 2 \times 10^5 1n2×105,

思路(值域):

1.等于左右的值域相同,右边的值域为2~2n,左边为1 ~ n 2 n^2 n2, 故最终值域应该为 2~2n 。

  1. 假设 a i ≤ a j a_i \leq a_j aiaj 那么 a i × a i ≤ 2 × n a_i \times a_i\leq 2\times n ai×ai2×n 。 而 b i = a i × a j − b j b_i=a_i \times a_j -b_j bi=ai×ajbj,所以我们遍历 a i a_i ai(O( n ) \sqrt{n}) n )),

    在遍历 a j 和 b j a_j 和 b_j ajbj (O(n)), 答案加上 b i b_i bi 的个数就可以

代码

void solve()
{
	cin>>n;
	vector<PII>c(n);
vector<int>cnt(n+1);
	for(int i=0;i<n;i++)
		cin>>c[i].first;
	for(int i=0;i<n;i++)
		cin>>c[i].second;
	int ans=0;
	sort(c.begin(),c.end());
	for(int s=1;s*s<=2*n;s++)//遍历a[i]
	{
		cnt.assign(n+1,0);
		for(auto [a,b]:c)
		{
			int v=s*a-b;
			if(v>=1&&v<=n)
				ans+=cnt[v];
			if(a==s) cnt[b]++;
		}
	}
	cout<<ans<<endl;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值