Educational Codeforces Round 7

Educational Codeforces Round 7

A:题意:给出一个序列,形式为1,1,2,1,2,3,1,2,3,4,......每个位置上是一个数而不是一个数位,为第n为是什么。(n<=10^14)

       好老的题了,就是等差数列,原本还想二分,看到n范围就果断枚举了。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
#define Int long long
using namespace std;
Int n;
int main() {
	cin>>n;
	Int i;
	for(i = 1;i <= 1e8;i ++)
	{
		if(((1ll + i) * i) / 2 >= n)
		{
			break;
		}
	}
	i = i - 1;
	cout<<n - ((1ll + i) * i) / 2;
	return 0;
}


B:题意:给出一个24小时制的时间,问过去n分钟之后的24小时制时间是多少。(n<=10^4)

      模拟就是了,如果答案是个位数就在前面添个0.

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
int getint() {
	char c = 'd';
	int ret = 0;
	while(c < '0' || c > '9') c = getchar();
	while(c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar();
	return ret;
}
int A,B,a,b;
int main() {
	A = getint();
	B = getint();
	a = getint();
	b = a % 60;
	a = a / 60;
	A += a;
	B += b;
	A = A + (B / 60);
	B %= 60;
	A %= 24;
	if(A <= 9) cout<<0<<A;
	else cout<<A;
	cout<<':';
	if(B <= 9) cout<<0<<B;
	else cout<<B;
	return 0; 
}


C:题意:给出一段序列,每次询问lr之间与x不相等的数出现在什么位置。(任意输出一个位置)。(序列长200000)

      一眼想到了树套树,明显数据结构学傻了。

      首先如果A[l]!=x,那么答案就是l,否则我们看与l不同的最近的下一个数在哪儿就行了,这个可以o(n)预处理。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
int n,m,A[200010],next[200010],l,r,x;
int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i ++) scanf("%d",&A[i]);
	next[n] = n + 1;
	for(int i = n - 1;i >= 1;i --)
		next[i] = (A[i] == A[i + 1]) ? next[i + 1] : i + 1;
	for(int i = 1;i <= m;i ++) 
	{
		scanf("%d%d%d",&l,&r,&x);
		if(A[l] != x) printf("%d\n",l);
		else printf("%d\n",(next[l] <= r) ? next[l] : -1);
	}
	return 0;
}
 


D:题意:给出n500000),你需要把1-n每个数两遍填入一个长为2*n的数组中,填之后有一个代价,代价就是对于每一个i,会产生(n-i)*|d(i)-n+i|的代价,代价之和就是答案,d(i)i这个数两个位置的距离。最小化代价,输出你填的序列。

      看了一看答案仿佛是0!!!因为我们只要保证每个数都相距n-i就行了,于是我们分奇数偶数进行构造,分别占n的长度,但是构造的时候发现n是个很大的麻烦,貌似会影响奇偶导致位置不够,我们有发现i=n是答案一定是0!!所以直接n--,吧其他的填完之后n随便填就可以了。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
int n,A[1000010];
int main() {
	scanf("%d",&n);
	for(int i = 1;i <= n - 1;i += 2) A[(i + 1) / 2] = A[n - i / 2] = i;
	for(int i = 2;i <= n - 1;i += 2) A[n + i / 2] = A[2 * n - i / 2] = i;
	for(int i = 1;i <= 2 * n;i += 1) 
		printf("%d ",(A[i] == 0) ? n : A[i]);
	return 0;
} 


E:题意:一棵树,根为1,每个叶子上有一只蚂蚁,每一时刻所有蚂蚁可以往父亲节点移一下,但是除了根之外不能有节点有同时两个蚂蚁存在,问所有蚂蚁到根的最短时间。(树大小5*10^5

      首先1的每棵子树一定是互相独立的。

      其次我们这样考虑,设当前仅仅在第i层有k只蚂蚁,那么时间一定是i+k-1,因为他们可以排成一条链一起往上跳!。

      所以说当有更深的节点存在时,我们这样考虑!设当前答案为x,在y层有一只蚂蚁(y>=x,按深度递增考虑)。

      如果x>=y,那么x+1,因为可以想成上面的点自己慢慢跑,而y层的这个点先跑到与上面相同层数去,再一起跑就行了,就相当于多了一个相同层的点。

      否则x=y,因为上面的点已经跑完了,但是y这只蚂蚁可能还没有及时跑到相同层(即没有和之前的蚂蚁接成一条链),所以总时间会被拖长。

      对于每个1的子树求一个x,那么max(x + 1)就是答案了。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
using namespace std;
struct dp{int dep;int num;
};dp Dp[500010];
struct node {int to;int next;
};node bian[1000010];
int size,first[500010],p[500010],Ans = -1,n,a,b,tot = 0;
bool comp(const dp &x,const dp &y) {return x.dep < y.dep;};
void inser(int x,int y) {
	size ++;
	bian[size].to = y;
	bian[size].next = first[x];
	first[x] = size;
}
void dfs(int x,int Anc,int depth) {
	int son = 0;
	for(int u = first[x];u;u = bian[u].next)
		if(bian[u].to != Anc)
			son ++,dfs(bian[u].to,x,depth + 1);
	if(son == 0) 
	{
		if(p[depth] == 0)
		{
			tot ++;
			p[depth] = tot;
			Dp[tot].num = 1;
 			Dp[tot].dep = depth;
		}
		else Dp[p[depth]].num ++;
	}
} 
int main() {
	scanf("%d",&n);
	for(int i = 2;i <= n;i ++) 
	{
		scanf("%d%d",&a,&b);
		inser(a,b);
		inser(b,a);
	}
	for(int u = first[1];u;u = bian[u].next)
	{
		for(int i = 1;i <= tot;i ++) 
			p[Dp[i].dep] = 0;
		tot = 0;
		dfs(bian[u].to,1,0);
		sort(Dp + 1,Dp + tot + 1,comp);
		int ret = -1;
		for(int i = 1;i <= tot;i ++)
			ret += (Dp[i].dep > ret) ? Dp[i].dep - ret + Dp[i].num - 1 : Dp[i].num;
		Ans = max(Ans,ret + 1);
	}
	cout<<Ans;
	return 0; 
}

    自觉忽略F题...

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值