Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2)题解

Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2)题解

A. Be Positive

题目大意

给出一个数组,让所有的数除去一个数,使得数组中正数的数量大于数组数量总数的一半(向上取整)

解题思路

统计正数的数量和负数的数量,如正数大于一半则除1,如负数大于一半则除-1,如都没有则无解

AC代码

#include
using namespace std;
int main()
{
	int n;
	scanf("%d",&n);
	int x;
	int a=0,b=0;
	for(int i=1;i<=n;i++) {
		cin>>x;
		if(x>0) a++;
		if(x<0) b++;
	}
	int len=n/2+n%2;
	if(a>=len) cout<<1<<endl;
	else if(b>=len)cout<<-1<<endl;
	else cout<<0<<endl;
}

B. Two Cakes

题目大意

给出一段长度为2n的序列其中为1~n中的数,每个数出现两次

解题思路

可以发现所有的数字向下一个数字时,选择向哪个数字没有后效性,因此直接从前向后比较即可

AC代码

#include
#define int long long 
using namespace std;
const int sz=2e5+5;
int a[sz];
int loc[sz][2];
int32_t main()
{
	int n;
	cin>>n;
	memset(loc,0,sizeof(loc));
	for(int i=1;i<=2*n;i++) cin>>a[i];
	for(int i=1;i<=2*n;i++)
	{
		if(loc[a[i]][0]==0) loc[a[i]][0]=i;
		else loc[a[i]][1]=i;
	}
	long long ans=loc[1][0]-1+loc[1][1]-1;
	for(int i=1;i<n;i++)
	{
		ans+=min(abs(loc[i][0]-loc[i+1][1])+abs(loc[i][1]-loc[i+1][0]),
				abs(loc[i][1]-loc[i+1][1])+abs(loc[i][0]-loc[i+1][0]));
	}
	cout<<ans<<endl;
}

C. Connect

题目大意

给出一张 n × n n\times n n×n的方阵图,其中每个方格分成陆地和海洋,人只能在陆地上行走,现能最多架起一座桥其成本为 ( r s − r t ) 2 + ( c s − c t ) 2 (r_s-r_t)^2+(c_s-c_t)^2 (rsrt)2+(csct)2其中 ( r s , c s ) , ( r t , c t ) (r_s,c_s),(r_t,c_t) (rs,cs),(rt,ct)分别为桥的起点和终点的坐标,现问,要从地图上一个点到另一个点,最少的架桥代价是多少

解题思路

dfs出所有的联通块,找出起点和终点所属的联通块,暴力枚举两个联通块之间的点对即可

AC代码

#include
using namespace std;
typedef pair<int,int> pii;
int m[55][55];
char s[55];
int vis[55][55];
int flag[55][55];
vector<pii> b[2505];
int n;
int cnt;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void dfs(int x,int y)
{
	for(int i=0;i<4;i++)
	{
		int xx=x+dir[i][0];
		int yy=y+dir[i][1];
		if(xx>=1&&xx<=n&&yy>=1&&yy<=n&&m[xx][yy]==0&&!vis[xx][yy])
		{
			vis[xx][yy]=1;
			flag[xx][yy]=cnt;
			b[cnt].push_back(pii(xx,yy));
			dfs(xx,yy);
		}
	}
}
int main()
{
	int r1,c1;
	int r2,c2;
	cin>>n;
	cin>>r1>>c1;
	cin>>r2>>c2;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++)
	{
		cin>>s+1;
		for(int j=1;j<=n;j++)
		{
			m[i][j]=s[j]-'0';
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(m[i][j]==0&&!vis[i][j])
			{cnt++;b[cnt].push_back(pii(i,j));flag[i][j]=cnt;vis[i][j]=1;dfs(i,j);}
		}
	}
	int beg=flag[r1][c1],end=flag[r2][c2];
	int ans=0x3f3f3f3f;
	for(auto bb:b[beg])
	{
		for(auto ee:b[end])
		{
			ans=min(ans,(bb.first-ee.first)*(bb.first-ee.first)+(bb.second-ee.second)*(bb.second-ee.second));
		}
	}
	cout<<ans<<endl;
}

D. Toy Train

题目大意

给出一个环,其上有n个火车站,每个站台有着一些的货物等待被拉到别的站台,火车每次经过时最多把一件货物装载上火车,但是可以卸下货物的数量没有限制,问从1~n个站点出发,每个站点把所有货物都运到目标站点,所需的最短时间(D1,D2题意相同,数据范围不同,故只分析数据范围更大的D2)

解题思路

对于每个点来说想要把这个点上所有的货物全部运完的最短时间总是确定的,其为货物的数量-1乘上周期长度再加上把所有这个点运出的货物运到目标站的中用时最短的那个时间

AC代码

#include
using namespace std;
typedef pair<int,int> pii;
int a[20005],b[20005];
vector<int> c[5005];
int lens[5005];
multiset<int> s;
int ans[5005];
int main()
{
   int n,m;
   cin>>n>>m;
   for(int i=1;i<=m;i++)
   {
   	cin>>a[i]>>b[i];
   	if(b[i]<a[i]) b[i]+=n;
   	c[a[i]].push_back(b[i]);
   }
   for(int i=1;i<=n;i++)
   {
   	if(c[i].size()==0) lens[i]=0;
   	else {
   		sort(c[i].begin(),c[i].end());
   		lens[i]=c[i][0]+(c[i].size()-1)*n;
   	}
   	s.insert(lens[i]);
   }
   for(int i=1;i<=n;i++)
   {
   	ans[i]=*(--s.end())-i;
   	if(lens[i]!=0)
   	s.erase(s.find(lens[i])),
   	s.insert(lens[i]+n);
   }
   for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
}
   	

E. Wrong Answer

题目大意

给出一段序列计算其 m a x 0 ≤ l ≤ r ≤ n − 1 ∑ l ≤ i ≤ r ( r − l + 1 ) ∗ a i max_{0\le l\le r\le n-1}\sum_{l\le i\le r}(r-l+1)*a_i max0lrn1lir(rl+1)ai其先给出了一种错误的解法

function find_answer(n, a)
    # Assumes n is an integer between 1 and 2000, inclusive
    # Assumes a is a list containing n integers: a[0], a[1], ..., a[n-1]
    res = 0
    cur = 0
    k = -1
    for i = 0 to i = n-1
        cur = cur + a[i]
        if cur < 0
            cur = 0
            k = i
        res = max(res, (i-k)*cur)
    return res

现给出一个k要求求出一个序列使得这个序列关于这个问题的正解和错误解的差距为k

解题思路

使得序列的第一项为-1.令整个序列的和为S.此时存在两个可能的正确答案 n S nS nS ( n − 1 ) ( S + 1 ) (n-1)(S+1) (n1)(S+1)当S大于等于1时,显然第一个更大,其差值为 S − n + 1 S-n+1 Sn+1因此贪心增加新元素即可

AC代码

#include
using namespace std;
const int loop=1e6;
int main()
{
	int k;
	cin>>k;
	vector<int> ans;
	ans.push_back(-1);
	int sum=-1;
	int cnt=1;
	while(sum-cnt+loop<k)
	{
		sum+=loop;
		cnt++;
		ans.push_back(loop);
	}
	ans.push_back(k-sum+cnt);
	cout<<ans.size()<<endl;
	for(auto x:ans) cout<<x<<' ';
}
	

你可能感兴趣的:(套题题解,codeforce)