首页 > 其他分享 >Codeforces Round 975 (Div. 2) A-E

Codeforces Round 975 (Div. 2) A-E

时间:2024-09-28 22:34:06浏览次数:8  
标签:975 int ll Codeforces long Div now id getchar

人生中第一次正常\(div2\)爆写5题。cf给我正反馈最大的一次

A直接找到最大的数字的位置,然后判断一下这个数字的位置下标的奇偶性就好了。然后如果有多个最大的就取奇数位置的。这样可以算出来一定是最优解

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read() {
	char c=getchar();int a=0,b=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
int n,a[101],f[101][101];
int main()
{
	int T=read();
	while(T--)
	{
		n=read();
		int Max=0,Maxid;
		for(int i=1;i<=n;i++)
		{
			a[i]=read();
			if(Max<=a[i])
			{
				if(Max==a[i])
				{
					Maxid=max(Maxid,i%2);
				}
				else Maxid=i%2;
				Max=a[i];
			}
		}
//		cout<<Maxid<<endl;
		if(n%2==0)
		{
			cout<<Max+n/2<<endl;
		}
		else
		{
			cout<<Max+n/2+(Maxid)<<endl;
		}
	}
	return 0;
}

B画个图,能看出来每个点的被覆盖次数就是左边的点数$\times \(右边点数,如果这个位置上本身就有点,就是\)(左边点数+1) \times (右边点数+1)-1\(。然后可以直接把这个放到一个下表为\)k\(的map中,询问就\)O(log(n))\(查询,总体\)(q\log n)$

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read() {
	char c=getchar();ll a=0,b=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
ll n,q,x[100001];
ll k[100001];
map<ll,ll> ma;
int main()
{
	ll T=read();
	while(T--)
	{
		n=read();q=read();
		for(ll i=1;i<=n;i++)
		{
			x[i]=read();
		}
		sort(x+1,x+1+n);
		ma.clear();
		for(ll i=1;i<n;i++)
		{
			ll sum=x[i+1]-x[i]-1;
			ma[i*(n-i)]+=sum;
			ma[(i+1)*(n-i)-1]++;
		}
		ma[n-1]++;
		for(ll i=1;i<=q;i++)
		{
			k[i]=read();
		}
		for(ll i=1;i<=q;i++)
		{
			cout<<ma[k[i]]<<' ';
		}
		cout<<endl;
	}
	return 0;
}

C人类智慧...卡我好久,和很久之前做的一个题目很像。这也导致我想歪了。和整除分块有一点点类似,但是还是不一样,把画个图把不等式写出来就结束了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read() {
	char c=getchar();ll a=0,b=1;
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;return a*b;
}
ll n,k,a[200001];
int main()
{
	ll T=read();
	while(T--)
	{
		n=read(),k=read();
		ll Max=0;ll sum=0;
		for(ll i=1;i<=n;i++)
		{
			a[i]=read();
			Max=max(Max,a[i]);
			sum+=a[i];
		}
		ll rsum=sum+k;
		ll ans=0;//×î½Ó½üµÄ¿¨×éÊý 
		for(ll i=n;i>=1;i--)//ºñ¶È 
		{
			if((rsum/i)>=((sum+i-1)/i)&&(rsum/i)>=Max)
			{
				ans=i;
				break;
			}
//			ll Ned=i*now;
//			if(Ned<=rsum)
//			{
//			}
//			if((i-1)*now<sum)//ÕâÖÖʱºò²ÅÐèÒªÔö¼Ó¿¨×éÊý 
//			{
//				ll back=
//			}
		}
		cout<<ans<<endl; 
	}
	return 0;
}
/*
1
5 4
2 6 1 2 4

*/

D比C简单很多,我开始看题到写完就花了20分钟image-20240928085450057
先考虑找到一个解,发现直接给所有城市按照ddl排序,然后从小的开始向大的覆盖,如果这样的操作是无解的,可以证明一定无解。
然后根据这个,可以推导出一个很重要的贪心,就是最后有解的城市一定是一个完整的答案区间。也就是能够作为起点的城市一定是一个连续的区间。
证明的话,根据我们判断是否有解的贪心可以感性理解,正确性还是挺明显的。
然后根据这个,先以ddl最小的点开始作为起点,向左右二分这个答案区间的边界,就能够找到答案。我写的是倍增,二分一样的。总复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
	int a=0,b=1;char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
	return a*b;
}
int n,b[200001];
struct city
{
	int id,ddl;
}a[200001];
bool cmp(city a,city b)
{
	return a.ddl<b.ddl;
}
int main()
{
	int T=read();
	while(T--)
	{
		n=read();
		for(int i=1;i<=n;i++)
		{
			b[i]=a[i].ddl=read();
			a[i].id=i;
		}
		sort(a+1,a+1+n,cmp);
		int st=a[1].id;
		int now=1,l,r;l=r=a[1].id;
		for(int i=2;i<=n;i++)
		{
			if(a[i].id<l)
			{
				now+=l-a[i].id;
				if(now>a[i].ddl)break;
				l=a[i].id;
			}
			if(a[i].id>r)
			{
				now+=a[i].id-r;
				if(now>a[i].ddl)break;
				r=a[i].id;
			}
		}
		if(!(l==1&&r==n))
		{
			cout<<0<<endl;
			continue;
		}
		int Maxl=st,Maxr=st;
		int nowm=19;
		while(nowm>=0)
		{
			if(Maxl-(1<<nowm)<=0)
			{
				nowm--;
				continue;
			}
			l=r=a[1].id;
			now=1;l=r=Maxl-(1<<nowm);
			for(int i=1;i<=n;i++)
			{
				if(a[i].id<l)
				{
					now+=l-a[i].id;
					if(now>a[i].ddl)break;
					l=a[i].id;
				}
				if(a[i].id>r)
				{
					now+=a[i].id-r;
					if(now>a[i].ddl)break;
					r=a[i].id;
				}
			}
			if((l==1&&r==n))Maxl-=(1<<nowm);
			nowm--;
		}
		nowm=19;
		while(nowm>=0)
		{
			if(Maxr+(1<<nowm)>n)
			{
				nowm--;
				continue;
			}
			l=r=a[1].id;
			now=1;l=r=Maxr+(1<<nowm);
			for(int i=1;i<=n;i++)
			{
				if(a[i].id<l)
				{
					now+=l-a[i].id;
					if(now>a[i].ddl)break;
					l=a[i].id;
				}
				if(a[i].id>r)
				{
					now+=a[i].id-r;
					if(now>a[i].ddl)break;
					r=a[i].id;
				}
			}
			if((l==1&&r==n))Maxr+=(1<<nowm);
			nowm--;
		}
		cout<<Maxr-Maxl+1<<endl;
	}
	return 0;
}

E题,我的做法很暴力,就是把所有点按照深度排序,然后每次就把相同深度的点和根节电拿出来建立虚树,然后计算这个虚数的边数,用\(n-1\)减去这个数字就是这个深度的答案。计算边数可以用lca,具体参考"异象石"这题。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
	int a=0,b=1;char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
	for(;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
	return a*b;
}
int n,head[1000001],tot,Size[500001],dep[500001][22],f[500001][22],dfn[500001],cnt;
struct edge
{
	int next,to;
}e[1000001];
inline void add(int i,int j)
{
	e[++tot].next=head[i];
	e[tot].to=j;
	head[i]=tot;
}
void pre(int x,int fa)
{
	Size[x]=1;f[x][0]=fa;dep[x][0]=dep[fa][0]+1;dfn[x]=++cnt;
	for(int i=head[x];i!=0;i=e[i].next)
	{
		int u=e[i].to;
		if(u==fa)continue;
		pre(u,x);
		Size[x]+=Size[u];
	}
}
int Lca(int x,int y)
{
	if(dep[x][0]<dep[y][0])swap(x,y);
	int now=21;
	while(now>=0)
	{
		if(dep[x][now]>dep[y][0])x=f[x][now];
		now--;
	}
	if(x==y)return x;
	now=21;
	while(now>=0)
	{
		if(f[x][now]!=f[y][now])x=f[x][now],y=f[y][now];
		now--;
	}
	return f[x][0];
}
inline Count(int x,int y)
{
	int lca=Lca(x,y);
	return dep[x][0]+dep[y][0]-dep[lca][0]*2;
}
vector<int> fdp[500001];
bool cmp(int a,int b)
{
	return dfn[a]<dfn[b];
}
int main()
{
	int T=read();
	while(T--)
	{
		for(int i=1;i<=tot;i++)head[i]=0;
		tot=0;
		n=read();
		for(int i=1;i<n;i++)
		{
			int x=read(),y=read();
			add(x,y);add(y,x);
		}
		cnt=0;
		dep[0][0]=-1;
		pre(1,0);
		for(int j=0;j<21;j++)
		{
			for(int i=1;i<=n;i++)
			{
				f[i][j+1]=f[f[i][j]][j];
				dep[i][j+1]=dep[f[i][j]][j];
			}
		}
		for(int i=0;i<=n;i++)fdp[i].clear();
		for(int i=0;i<=n;i++)
		{
			fdp[dep[i][0]].push_back(i);
		}
		int ans=0;
		for(int i=0;i<=n;i++)
		{
			if(fdp[i].size()==0)continue;
			sort(fdp[i].begin(),fdp[i].end(),cmp);
			int sum=0,Alllca=Lca(fdp[i][0],fdp[i][fdp[i].size()-1]);
			for(int j=0;j<fdp[i].size()-1;j++)
			{
				sum+=Count(fdp[i][j],fdp[i][j+1]);
				Alllca=Lca(Alllca,fdp[i][j]);
			}
			sum+=Count(fdp[i][0],fdp[i][fdp[i].size()-1]);
			sum/=2;
			sum+=dep[Alllca][0];
//			cout<<i<<' '<<sum<<' '<<Alllca<<' '<<dep[Alllca][0]<<endl;
			ans=max(ans,sum);
		}
		cout<<(n-1)-ans<<endl;
	}
	return 0;
}

标签:975,int,ll,Codeforces,long,Div,now,id,getchar
From: https://www.cnblogs.com/HLZZPawa/p/18438537

相关文章

  • Codeforces Round 975 Div.2 C题 解析
    C题题目链接:Problem-C-Codeforces题目描述思路......
  • Codeforces Round 975 (Div. 2) 题解:D、E
    第一次进前50,上分最爽的一次D.Speedbreaker对\(a\)按照时间升序排序,不难发现,对于升序排序后的数组,当我们搜到时间\(t\)时,记录已经搜过的时间对应原城市编号最小值为\(l\),最大值为\(r\),则我们一定要在\(a_t\)时间之前走过所有\([l,r]\)之间的城市。则若\(r-l+1>a_t\)则无解,因......
  • Codeforces Round 944 (Div. 4) A~G题解
    A\(min\)函数和\(max\)函数的使用,按照格式输出即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpair<int,int>PII;voidsolve(){intx,y;cin>>x>>y;cout<<min(x,y)<<'......
  • Codeforces Round 973题解(E)
    E.PrefixGCD假设我们从一个空集合\(b\)开始,不断从\(a\)数组中选择一个元素添加到\(b\)集合的尾部,当把\(a\)数组的元素全部添加到\(b\)中后,得到的\(b\)即为所求的rearrange后的\(a\)。结论1:每次选择使得其和当前\(b\)中所有元素的最大公约数最小的那个\(a_i\)加入到\(b\)的末......
  • [CERC2015] Digit Division 题解
    \(O(n^2)\)做法和大部分人最开始一样,我也想的是DP。设\(dp_i\)表示用前面\(i\)个字符拆分得到的答案。既然是统计方案数,我们肯定是根据前面的答案累加。考虑在\([1,i-1]\)中选择一个\(j\),如果\([j+1,i]\)的字符组成的数字能够被\(m\)整除,那么\(dp_i\)就可以累加......
  • codeforces round 971(div4)E(二分答案,禁用数学方法)
    解题历程:开始想的是用数学公式的方法,利用公式推出二次函数,再求出根,再用根求出答案,检查了一个小时,结果怎么改都有细微的偏差,最后发现答案先单调递减在单调递增,那么可以用二分答案的方法查找最小的答案,二分对细节的处理要求比较高,于是在二分中加入了一个限制,当二分的区间小于5时,就......
  • [ABC234G] Divide a Sequence
    [ABC234G]DivideaSequence给定长度为\(N\)的序列\(A\),我们定义一种将\(A\)划分为若干段的方案的价值为每一段的最大值减去最小值的差的乘积,你需要求出所有划分方案的价值的总和,答案对\(998244353\)取模。$1\\leq\N\\leq\3\\times\10^5$$1\\leq\A_i\\leq......
  • Codeforces Round 971 (Div. 4)题解记录(G3待补)
    A.Minimize!暴力模拟一遍即可#include<iostream>#include<queue>#include<deque>#include<map>#include<set>#include<stack>#include<vector>#include<bitset>#include<math.h>#include<random>#include&l......
  • Codeforces Round 970 (Div. 3)A~F
    CodeforcesRound970(Div.3)A~FA.Sakurako'sExam把1的个数和2的个数按奇偶分类讨论即可。//AConemoretimes//nndbk#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintmod=1e9+7;constintN=2e5+10;intmain(){ios......
  • Codeforces Round 964 (Div. 4)A~G1
    CodeforcesRound964(Div.4)A~G1A.A+BAgain?签到//AConemoretimes//nndbk#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constintmod=1e9+7;constintN=2e5+10;intmain(){ios::sync_with_stdio(false);ci......