首页 > 其他分享 >Codeforces Round 862 (Div. 2) A-D题解

Codeforces Round 862 (Div. 2) A-D题解

时间:2023-04-03 22:56:55浏览次数:43  
标签:pre 结点 int 题解 void 862 距离 Div dp

比赛地址

A. We Need the Zero

题意:给出一个数组,对任意1<=i<=n,令bi=aix,问是否存在x,使得b<sub>1</sub>b2...bn=0

Solution

如果n为奇数,那么x一定存在,因为偶数个x异或得到的是0,直接令x=0(a<sub>1</sub>a2...an)即可

如果n为偶数,那么x取任何值都不会影响结果,所以只用看a1a<sub>2</sub>...^an是否为0即可

void solve()
{
	int n;cin>>n;
	int sum;
	for(int i=1;i<=n;i++)
	{
		int x;cin>>x;
		if(i==1)sum=x;
		else sum^=x;
	}
	if(n&1)cout<<(0^sum)<<"\n";
	else 
	{
		if(sum==0)cout<<"1\n";
		else cout<<"-1\n";
	}
}

B. The String Has a Target

题意:给出一个字符串,要求进行一次且仅进行一次操作,使得操作后的字符串字典序最小

操作:选择一个字符,将其移到字符串首

Solution

对直接从头到尾遍历最小的字符的位置即可

void solve()
{
	int n;cin>>n;
	string s;cin>>s;
	char f=s[0];
	int pos=0;
	for(int i=1;i<n;i++)
	{
		if(s[i]<=s[pos])
		{
			pos=i;
		}
	}
	cout<<s[pos];
	for(int i=0;i<n;i++)
	{
		if(i!=pos)cout<<s[i];
	}
	cout<<"\n";
	
}

C. Place for a Selfie

题意:给出n条解析式为y=kx的直线的k,和m条解析式为y=ax2+bx+c的抛物线的a,b,c,对每一条抛物线进行询问:是否存在一条直线与该抛物线不相交也不相切,并给出任意一条直线的k值

Solution

令ax2+bx+c=kx,于是我们可以得到ax2+(b-k)x+c=0

根据判别式可得,当满足题意的直线存在时,满足不等式(b-k)2<4ac

于是我们需要找到离b最近的k值,对k由小到大排序,进行二分查找即可

void solve()
{
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>k[i];
	sort(k+1,k+1+n);
	for(int i=1;i<=m;i++)
	{
		int a,b,c;cin>>a>>b>>c;
		if(c<0)cout<<"NO\n";
		else
		{
			int l=1,r=n;
			while(l<r)
			{
				int mid=(l+r)>>1;
				if(k[mid]<b)l=mid+1;
				else r=mid;
			}
			int x=b-k[l];
			int flag=0;
			if(x*x<4*a*c)flag=1;
			if(l>1)
			{
				int y=b-k[l-1];
				if(y*y<4*a*c)
				{
					flag=1;
					l--;
				}
			}
			if(flag)
			{
				cout<<"YES\n";
				cout<<k[l]<<"\n";
			}else cout<<"NO\n";
			
		}
	}
	cout<<"\n";
}

D. A Wide, Wide Graph

题意:给出一棵树,令图Gk上的结点与树相同,在树的任意两个点<u,v>,当<u,v>的距离大于等于k时,将<u,v>的边加入到图Gk中,询问对于k=1,2,...,n,Gk有多少个连通分量

Solution

对于一个结点,如果他所能到达的最远的距离小于k,它才会被独立成一个连通分量

于是问题就转变为了如何求所有结点所能到达的最大距离

不难发现结点i能到达的最大距离d[i]=max(f[i],g[pre]),其中f[i]表示从i向下的子树走所能到达的最大距离,g[pre]表示从父节点pre能走的最长距离,这个距离可以向i的兄弟结点走,也可以向pre的父节点继续走直到走到头

对于前一种向子树走,我们可以用树形dp来求

void dfs(int x,int pre)
{
	dp[x]=0;
	for(auto it:e[x])
	{
		if(it!=pre)
		{
			dfs1(it,x);
			if(dp[it]+1>dp[x])dp[x]=dp[it]+1;
		}
	}
}

但是对于第二种就有点麻烦了,首先我们需要预处理出从i开始向子树走所能到达的第二大的距离,第一大和第二大的距离分别设为为dp[i] [0]和dp[i] [1],因为要如果从兄弟结点开始走,就需要判断dp[pre] [0]对应的子结点是不是i,如果是i则距离最长为dp[pre] [1]加上到pre的距离,如果不是i,那么就是dp[pre] [0]加上到pre的距离,最后再与g[pre]作比较,从而得到g[i]

这里直接把g[i]设为dp[i] [2]

void dfs1(int x,int pre)  //预处理从x向子树走的最大距离和第二大距离以及最大距离对应的子结点
{
	dp[x][0]=dp[x][1]=dp[x][2]=0;
	for(auto it:e[x])
	{
		if(it!=pre)
		{
			dfs1(it,x);
			if(dp[it][0]+1>dp[x][0])
			{
				to[x]=it;
				dp[x][1]=dp[x][0];
				dp[x][0]=dp[it][0]+1;
			}else if(dp[it][0]+1>dp[x][1])
			{
				dp[x][1]=dp[it][0]+1;
			}
		}
	}
}
void dfs2(int x,int pre)  //处理从x向兄弟结点或者向父节点的父节点走的最大距离
{
	for(auto it:e[x])
	{
		if(it!=pre)
		{
            //这里注意因为是从上往下修改的,所以是先修改再进行遍历,而不是一般树形dp的先看子结点再看父节点
			dp[it][2]=max(dp[x][2],to[x]==it?dp[x][1]:dp[x][0])+1;
			dfs2(it,x);
		}
	}
}

预处理跑完后,剩下的就是把最大距离小于k的点都去掉,去掉的点数+1就是连通分量个数了

void dfs1(int x,int pre)
{
	dp[x][0]=dp[x][1]=dp[x][2]=0;
	for(auto it:e[x])
	{
		if(it!=pre)
		{
			dfs1(it,x);
			if(dp[it][0]+1>dp[x][0])
			{
				to[x]=it;
				dp[x][1]=dp[x][0];
				dp[x][0]=dp[it][0]+1;
			}else if(dp[it][0]+1>dp[x][1])
			{
				dp[x][1]=dp[it][0]+1;
			}
		}
	}
}
void dfs2(int x,int pre)
{
	for(auto it:e[x])
	{
		if(it!=pre)
		{
			dp[it][2]=max(dp[x][2],to[x]==it?dp[x][1]:dp[x][0])+1;
			dfs2(it,x);
		}
	}
}

void solve()
{
	int n;cin>>n;
	
	for(int i=1;i<n;i++)
	{
		dp[i][0]=dp[i][1]=dp[i][2]=0;
		int u,v;cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs1(1,0);
	dfs2(1,0);
	for(int i=1;i<=n;i++)
	{
		a[i]=max(dp[i][0],dp[i][2]);
		//cout<<a[i]<<" ";
	}

	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++)
	{
		int l=1,r=n;
		while(l<r)
		{
			int mid=(l+r)>>1;
			if(a[mid]<i)l=mid+1;
			else r=mid;
		}
		if(a[l]>=i)cout<<l<<" ";
		else if(a[l]<i)cout<<n<<" ";
		
	}
	
	cout<<"\n";
}

标签:pre,结点,int,题解,void,862,距离,Div,dp
From: https://www.cnblogs.com/HikariFears/p/17284790.html

相关文章

  • Codeforces Round 862 (Div. 2) (4.2)
    CodeforcesRound862(Div.2)A-WeNeedtheZero思路:某个数被异或两次相当于没变,即判断n的奇偶性;n为偶数时判断所有数异或后的数是否为0,若为0,输出任意数;n为奇数时答案为所有数异或后的值#include<bits/stdc++.h>usingnamespacestd;typedefpair<int,int>PII;consti......
  • 个人向口胡题解(4/3)
    ABC295F题意:十进制下,给定两个正整数\(L、R\)和一个字符串\(S\),设\(F(x)\)为\(S\)在\(x\)中一共出现多少次,求\(\sum_{x=L}^{R}F(x)\)。如\(S=22,F(122)=1,F(123)=0,F(222)=2\)思路:可以按\(S\)在\(x\)中匹配的位置分别计算贡献,匹配的位置知道了,那么合法的数个数就是这位的贡献......
  • Codeforces Round 862 (Div. 2)A-C思路复盘
    感觉这场前三题都简单,复盘一下赛时的脑回路QAQ,c二分wa了四发赛后才过的血亏A题意:问是否能找到一个数x,有\(b_i=a_i⊕x\),使得\(b\)数组的总异或和为0。思路:赛时模拟样例可以发现先把a数组的总异或和求出来假设为x,然后由异或性质可知相同为0,不同为1,可知这个x可能就是答案。然......
  • css 设置 div等于屏幕的时候直角,小于屏幕圆角
    .card{border-radius:clamp(0px,((100vw-4px)-100%)*9999,8px);}clamp()clamp()函数的作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用。它接收三个参数:最小值、首选值、最大值。......
  • 加载更多 - 监听div的滚动scroll
    前言:某些情况下,在展示列表数据时,为了实现性能优化及用户更好的体验,可以先展示十几条数据,然后边滑动边加载更多,可以减少服务器压力及页面渲染时间。varpageNum=1;//页数vardomHeight=$(".listBox").height()*4;vardom=document.getElementById('list');dom.addEventList......
  • win10计划任务程序库实现定时任务的自动执行程序及问题解决。
    win10计划任务程序库可以实现按照规则频率执行脚本的功能。现在将设置方法记录如下:创建任务步骤1、右键点击我的电脑,选择管理,依次点击:系统工具-》任务计划程序-》任务计划程序库。 2、点击最右侧操作中的创建基本任务,打开下面的弹窗。 3、创建任务的基本信息,下一步选择......
  • 分治(Divide and Conquer)算法之归并排序
    顾名思义,分治问题由“分”(divide)和“治”(conquer)两部分组成,通过把原问题分为子问题,再将子问题进行处理合并,从而实现对原问题的求解。我们在排序章节展示的归并排序就是典型的分治问题,其中“分”即为把大数组平均分成两个小数组,通过递归实现,最终我们会得到多个长度为1的子数组;“......
  • 问题解决-jdk配置问题
    我这里其实犯了一个低级错误。jdk的版本配置问题。之前报500实例化Servlet类[testServlet]异常就是这个问题。看图    这两个地方的版本一定要相同,不然报错是肯定的。虽然是很低级的问题,但是却真的会遇到,一不小心就弄错了。......
  • CodeTON Round 4 (Div. 1 + Div. 2, Rated, Prizes!)- Make It Permutation
    题目链接:Problem-C-Codeforces  #include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;#defineendl"\n"intmain(){ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);intT=1;cin>>T;while(......
  • CodeTON Round 4 (Div. 1 + Div. 2, Rated, Prizes!)
    题目链接C核心思路其实这个操作无非就两种:插入和删除。我们可以把重复的元素都先删除,因为这肯定是每个操作必须要做的。我们可以从最基础的情况出发也就是怎么构造出来\(1\sima[i]\)的序列呢。肯定是吧\(i\simn\)之后的序列都删除吧,然后把前面缺少的再补上去吧。所以我们......