题解 - Codeforces Round #635 (Div. 2,A-E)

C o d e f o r c e s   R o u n d   635   ( D i v . 2 ) \mathrm{Codeforces\ Round \ 635 \ (Div. 2) }

吐槽环节

  • 比赛就做出 4 4 道, D   f s t D\ fst
  • 中国场果真毒瘤

A . I c h i h i m e   a n d   T r i a n g l e \mathrm{A.Ichihime\ and\ Triangle}

题目意思

S o l \mathrm{Sol}

  • s h a b b y shabby 题目,因为是随便构造。所以我们只要强制两根长的木棒相等就可以了,保证满足条件的。
  • 时间复杂度: O ( 1 ) O(1)

C o d e \mathrm{Code}

#include <bits/stdc++.h>
#define pb push_back
using namespace std;

inline int read()
{
	int sum=0,ff=1; char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while(isdigit(ch))
		sum=sum*10+(ch^48),ch=getchar();
	return sum*ff;
}

int Q,a,b,c,d;

int main()
{
	Q=read();
	for (;Q--;)
	{
		a=read();
		b=read();
		c=read();
		d=read();
		printf("%d %d %d\n",b,c,c);
	}
	return 0;
}

B . K a n a   a n d   D r a g o n   Q u e s t   g a m e \mathrm{B.Kana\ and \ Dragon \ Quest \ game}

题目意思

S o l \mathrm{Sol}

  • 又是简单题( A , B A,B 两题共 6 6 分钟就可以做完很正常。。。
  • 我们就先不停地能使用操作 1 1 就用直到 x 10 x\leq 10 ,我们再用操作 2 2 。然后就判断这样过后剩余的 x x 0 0 比一比就好了。
  • 时间复杂度: O ( log x ) O(\log x)

C o d e \mathrm{Code}

#include <bits/stdc++.h>
#define pb push_back
using namespace std;

inline int read()
{
	int sum=0,ff=1; char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while(isdigit(ch))
		sum=sum*10+(ch^48),ch=getchar();
	return sum*ff;
}

int Q,a,b,c,d;

int main()
{
	Q=read();
	for (;Q--;)
	{
		a=read();
		b=read();
		c=read();
		while(b>0&&a>10)
		{
			a=a/2+10;
			b--;
		} 
		if(a<=c*10) puts("YES");
		else puts("NO");
	}
	return 0;
}

C . L i n o v a   a n d   K i n g d o m \mathrm{C.Linova\ and \ Kingdom}

题目意思

S o l \mathrm{Sol}

  • 一道简单的结论题目
  • 那么选节点 x x 时,增加的答案 D e p x 1 Dep_x-1 ,因为它成功变为了那个选择点节点,同时减少的答案为 S i z x 1 Siz_x - 1 ,因为它的子树节点都少了一个。
  • 那么答案就是前 K K 大的 D e p x S i z x Dep_x-Siz_x
  • 时间复杂度: O ( n log n ) O(n \log n)

C o d e \mathrm{Code}

#include <bits/stdc++.h>
#define pb push_back
#define int long long 
using namespace std;

inline int read()
{
	int sum=0,ff=1; char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while(isdigit(ch))
		sum=sum*10+(ch^48),ch=getchar();
	return sum*ff;
}

const int N=2e5+5;

int n,m,dep[N],a[N],siz[N],ans;
vector<int> G[N];

inline void dfs(int u,int fa)
{
	dep[u]=dep[fa]+1;
	siz[u]=1;
	for ( int i=0;i<G[u].size();i++ )
	{
		int v=G[u][i];
		if(v==fa) continue;
		dfs(v,u);
		siz[u]+=siz[v];
	}
	a[u]=dep[u]-siz[u];
}

signed main()
{
	n=read();
	m=read();
	for ( int i=1;i<n;i++ )
	{
		int x,y;
		x=read();
		y=read();
		G[x].pb(y);
		G[y].pb(x);
	}
	dfs(1,0);
	sort(a+1,a+n+1);
	reverse(a+1,a+n+1);
	for ( int i=1;i<=m;i++ ) ans+=a[i];
	printf("%lld\n",ans);
	return 0;
}

D . X e n i a   a n d   C o l o r f u l   G e m s \mathrm{D.Xenia\ and \ Colorful\ Gems}

题目意思

S o l \mathrm{Sol}

  • 一道比较简单的题目,但是比赛时 f s t fst 啦,赛后仔细想想开始想错了。
  • 我们考虑一个简单的性质:就是如果选了 A A 中的一个球 x x ,那么 B , C B,C 中想让答案小是不是只要试图去接近他就可以了。然后 B , C B,C 同理。
  • 这样我们就对 A , B , C A,B,C 各自做一遍。然后找到对应另外两个中与他接近的(具体地看代码吧
  • 时间复杂度: O ( k n log n ) O(k*n\log n) , k k 为常数

C o d e \mathrm{Code}

#include <bits/stdc++.h>
#define int long long 
using namespace std;

inline int read()
{
	int sum=0,ff=1; char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while(isdigit(ch))
		sum=sum*10+(ch^48),ch=getchar();
	return sum*ff;
}

const int N=1e5+5;

int Q,na,nb,nc,ans;
int a[N],b[N],c[N];

inline int Calc(int x,int y,int z)
{
	return (x-y)*(x-y)+(z-x)*(z-x)+(y-z)*(y-z);
}

signed main()
{
	Q=read();
	for (;Q--;)
	{
		na=read(),nb=read(),nc=read();
		for ( int i=1;i<=na;i++ ) a[i]=read();
		for ( int i=1;i<=nb;i++ ) b[i]=read();
		for ( int i=1;i<=nc;i++ ) c[i]=read();
		sort(a+1,a+na+1);
		sort(b+1,b+nb+1);
		sort(c+1,c+nc+1);
		ans=1e19;
		for ( int i=1;i<=na;i++ )
		{
			int pb=upper_bound(b+1,b+nb+1,a[i])-b;//找到第一个比它大的
			int pc=upper_bound(c+1,c+nc+1,a[i])-c;
			int pbb=pb-1,pcc=pc-1;//找到最大的小于等于这个球的,下面同理
			if(pb<=nb)
			{
				if(pc<=nc) ans=min(ans,Calc(a[i],b[pb],c[pc]));
				if(pcc>=1) ans=min(ans,Calc(a[i],b[pb],c[pcc]));
			}
			if(pbb>=1)
			{
				if(pc<=nc) ans=min(ans,Calc(a[i],b[pbb],c[pc]));
				if(pcc>=1) ans=min(ans,Calc(a[i],b[pbb],c[pcc]));
			}
		}
		for ( int i=1;i<=nb;i++ )
		{
			int pa=upper_bound(a+1,a+na+1,b[i])-a;
			int pc=upper_bound(c+1,c+nc+1,b[i])-c;
			int paa=pa-1,pcc=pc-1;
			if(pa<=na)
			{
				if(pc<=nc) ans=min(ans,Calc(b[i],a[pa],c[pc]));
				if(pcc>=1) ans=min(ans,Calc(b[i],a[pa],c[pcc]));
			}
			if(paa>=1)
			{
				if(pc<=nc) ans=min(ans,Calc(b[i],a[paa],c[pc]));
				if(pcc>=1) ans=min(ans,Calc(b[i],a[paa],c[pcc]));
			}
		}
		for ( int i=1;i<=nc;i++ )
		{
			int pb=upper_bound(b+1,b+nb+1,c[i])-b;
			int pa=upper_bound(a+1,a+na+1,c[i])-a;
			int pbb=pb-1,paa=pa-1;
			if(pb<=nb)
			{
				if(pa<=na) ans=min(ans,Calc(c[i],b[pb],a[pa]));
				if(paa>=1) ans=min(ans,Calc(c[i],b[pb],a[paa]));
			}
			if(pbb>=1)
			{
				if(pa<=na) ans=min(ans,Calc(c[i],b[pbb],a[pa]));
				if(paa>=1) ans=min(ans,Calc(c[i],b[pbb],a[paa]));
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

E . K a a v i   a n d   M a g i c   S p e l l \mathrm{E.Kaavi\ and \ Magic \ Spell}

题目意思

S o l \mathrm{Sol}

  • 一道区间 D P DP 题目
  • 首先我们考虑如果那个串的长度已经大于 T |T| ,且前缀为 T T 后面就可以任意填了。
  • 那么我们设 f l , r f_{l,r} 表示填的那个串与 T T 匹配了 [ l , r ] [l,r] 的方案数
  • 那么转移如下
    • f l , r = f l , r + f l + 1 , r [ S i = T l ] f_{l,r}=f_{l,r}+f_{l+1,r} [S_i=T_l]
    • f l , r = f l , r + f l , r 1 [ S i = T r ] f_{l,r}=f_{l,r}+f_{l,r-1} [S_i=T_r]
    • 对于 i > m i>m 的两个都可以转移
  • 那么 a n s = i = m n f 1 , i ans=\sum_{i=m}^{n} f_{1,i}
  • 时间复杂度: O ( n 2 ) O(n^2)

C o d e \mathrm{Code}

#include <bits/stdc++.h>
#define pb push_back
using namespace std;

inline int read()
{
	int sum=0,ff=1; char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-') ff=-1;
		ch=getchar();
	}
	while(isdigit(ch))
		sum=sum*10+(ch^48),ch=getchar();
	return sum*ff;
}

const int N=3005;
const int mo=998244353;

int n,m,f[N][N],ans;
char ch[N],th[N];

int main()
{
	scanf("%s",ch+1);
	scanf("%s",th+1);
	n=strlen(ch+1);
	m=strlen(th+1);
	for ( int i=1;i<=n+1;i++ ) f[i][i-1]=1;
	for ( int i=1,len=1;i<=n;i++,len++ ) 
		for ( int l=1,r=l+len-1;r<=n;l++,r++ ) 
		{
			if(l>m||ch[i]==th[l]) 
				f[l][r]=(f[l][r]+f[l+1][r])%mo;
			if(r>m||ch[i]==th[r]) 
				f[l][r]=(f[l][r]+f[l][r-1])%mo;
		}
	for ( int i=m;i<=n;i++ ) ans=(ans+f[1][i])%mo;
	printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wangyiyang2/article/details/105551886