第二次训练:Educational Codeforces Round 77 (Rated for Div. 2)

1.Educational Codeforces Round 77 (Rated for Div. 2) F
在这里插入图片描述
题意:有n个数代表不同种颜色,每个数都有一定的取值范围。最后求一个总的dis值。看示例的解析应该这些就够了,但关键不明白的就是多出来的这三行,说是这棵树的边,实在不明白干什么用的。连题目都看不懂,搜了半天也没找到有谁解释下这个题,那多出来的n-1行啥意思,就更不会做了。当然,官方题解就是一个秀儿。
2.Educational Codeforces Round 77 (Rated for Div. 2) D
在这里插入图片描述在这里插入图片描述
题意:有m个士兵,k个陷阱,知道要到达的终点n(到达n+1)和要求的时间,每个士兵有一定的血量,每个陷阱也有陷阱本身的位置,解除陷阱的位置和一定的伤害值。而自己作为玩家和所有士兵从原点开始。每个时间单位可以选择自己移动一个单位或者自己和士兵小队(自己选择移动哪些士兵)同时移动一个单位。求规定时间内最多能够运送多少士兵到达终点。
  这个题光看题目就花了十好几分钟,虽然是看懂了,但我当时就知道这个题我不可能做了。光是在做题时记住每个变量的含义就很麻烦了,更别说题目不可能读懂题意就能做出来了。我当时猜测这应该是最难的,没想到难度是D。要注意的是,只能由玩家排雷后才能带领士兵通过,而且走的每一步都要花时间,所以最优的方法一定是先尽可能排除一定的陷阱,然后将能够撑得住到达终点尽可能多的士兵一次性运到终点(士兵一定是尽量挑血量最厚的)。
  也就是说,角色需要先走一段路排陷阱,然后回去带上小队的某些人再到终点,或者说,这段排陷阱的路要走三遍,然后走完剩下的路。当然,士兵可能很多,所以最好二分一下。

#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<ostream>
#include<istream>
typedef long long ll;
using namespace std;
#define mod 1e9+7
#define PI acos(-1.0)
const ll maxn=200000;
const int mx=maxn+10;
struct node {
	int l,r;
	int d;
	bool operator < (node A) const
	{
		return r < A.r;
	}
} s[mx];
int sum[mx];
int a[mx];
int n,m,K,t;
bool check(int mid) {
	for (int i=0;i<=n;i++) sum[i] = 0;
	for (int i=1;i<=K;i++) {
		if (s[i].d > mid) {
			sum[s[i].l]++;
			sum[s[i].r+1]--;
		}
	}
	int len = 0;
	for (int i=1;i<=n;i++) {
		sum[i] += sum[i-1];
		len += (sum[i] != 0);
	}
	int ret = len*3 + (n+1-len);
	return ret <= t;
}
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(0);
    /*int t;
    cin>>t;
    for(int o=1;o<=t;o++)
    {

    }*/
    cin>>m>>n>>K>>t;
	int l = 0,r = m;
	for (int i=1;i<=m;i++)
		cin>>a[i];
	sort(a+1,a+1+m,greater<int>());
	for (int i=1;i<=K;i++) {
		cin>>s[i].l>>s[i].r>>s[i].d;
	}
	a[0] = 1e6;
	while (l < r) {
		int mid = l+r+1>>1;
		if (check(a[mid]))
			l = mid;
		else
			r = mid - 1;
	}
	cout<<l<<endl;
}

3.Educational Codeforces Round 77 (Rated for Div. 2) A
在这里插入图片描述
题意:输入n,k,求k分成n份后每份平方,求最小的平方后的和。
  没啥技巧,往小了分就好。

#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<ostream>
#include<istream>
typedef long long ll;
using namespace std;
#define mod 100000
#define PI acos(-1.0)
const ll maxn=200000;
ll n,m,a[20000],ans,aans,step;

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(0);
    int t;
    cin>>t;
    for(int o=1;o<=t;o++)
    {
        cin>>m>>n;
        if(!n%m) cout<<m*(n/m)*(n/m)<<endl;
        else cout<<(n/m)*(n/m)*(m-n%m)+(n/m+1)*(n/m+1)*(n%m)<<endl;
    }
}

4.Educational Codeforces Round 77 (Rated for Div. 2) E
在这里插入图片描述在这里插入图片描述
题意:给定一个包含偶数个元素的数组,每次两两一组下标大的留下重复操作,想在想让值为-1的元素最终留下,那么就在分组的另一个元素下标较大时花费另一个元素的值来淘汰原本应该留下的元素,问如何分组使得花费最小,输出最小的花费。借鉴了官方题解的代码。

#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<ostream>
#include<istream>
typedef long long ll;
using namespace std;
#define mod 1e9+7
#define PI acos(-1.0)
const ll maxn=200000;
const ll inf=1e18;
const int mx=(1<<20)+99;
ll dp[mx][19];
int pr[30];
int a[mx];
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(0);
    /*int t;
    cin>>t;
    for(int o=1;o<=t;o++)
    {

    }*/
    int n,pos;
	cin>>n;
	pr[0]=1;
	for (int i=1;i<30;i++)
		pr[i]=pr[i-1]*2;
	int mi=1e9,bit=0;
	for (int i=1;i<=n;i++) {
		cin>>a[i];
		mi = min(a[i],mi);
		if (mi != -1) a[i] = 0;
		if (a[i] == -1) pos = i;
	}
	while ((1<<bit)!=n) bit++;
	for (int j=1;j<=bit;j++)
		dp[0][j] = inf;
	dp[0][0] = 0;
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=bit;j++)
		{
			dp[i][j]=dp[i-1][j];
			if (a[i]==-1) continue;
			int mv=pr[j]-2+(pos<i);
			if (mv<i)
            dp[i][j] = min(dp[i][j],dp[i-1][j-1]+a[i]);
		}
	}
	cout<<dp[n][bit]<<endl;
}

还看到了一个思路非常奇特,代码很帅气的题解,当然,上面标着思路来源于B站。
在这里插入图片描述


#include<bits/stdc++.h>
using namespace std;
const int N=(1<<18)+5;
typedef long long ll;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define sci(a) scanf("%d",&(a))
int n,a[N];
bool ok[N];
priority_queue<int,vector<int>,greater<int> >q;
ll ans;
int main(){
    sci(n);
    rep(i,1,n){
        sci(a[i]);
    }
    rep(i,0,18){
        ok[1<<i]=1;
    }
    per(i,n,1){
        if(a[i]==-1)break;
        q.push(a[i]);
        if(ok[i]){
            ans+=q.top();
            q.pop();
        }
    }
    printf("%lld\n",ans);
    return 0;
}
————————————————
版权声明:本文为CSDN博主「Code92007」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Code92007/article/details/106935915

5.Educational Codeforces Round 77 (Rated for Div. 2) C
在这里插入图片描述
题意:输入a,b,对a,b的倍数(包括0)涂色(公倍数可任意涂),求是否可以做到少于连续的c个涂色不会是同一个颜色。
  乍一看到这个题目我以为这个题目才是B题的难度,认为只要做到小的那个数的c倍不会超过大的那个数就可以做到了。提交错了才感觉没那么简单。所以过了一会找了几个特殊值研究了一下发现了一组不合要求的数据,而且我当时几乎可以确定只要这组数据的问题解决了就可以了。这组数据就是7,11和2。按照上面做法这个是可以的,但列下标发现7 11 14 21 22 28这段数中就出现了14和21涂同样颜色的情况,而出现这个的原因就是7和11间的这个差值4。会和它有关的有可能是c值,也可能是7和11的最大公约数这里是1,也可能和这两个都有关,所以我决定一个一个试试,但因为开始时我求了a,b最大公约数(这也是为什么我会想到会跟最大公约数有关)以得到a,b互质的两个数(因为我感觉可能和这个有关,实际没关系),所以差值不是实际两个数的差值,而且判断成立后c值不减反加,所以都没对,最后改正后发现是和最大公约数有关。其实最先测试的就是这个最大公约数,只不过因为别的错误没发现它。当然,看过别人的代码后发现,自己的做法真是爬模滚打坑蒙拐骗做出来的。。。

#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<ostream>
#include<istream>
typedef long long ll;
using namespace std;
#define mod 100000
#define PI acos(-1.0)
const ll maxn=200000;
ll n,m,k,a[20000],minn,maxx;
ll gcd(ll,ll);
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(0);
    int t;
    cin>>t;
    for(int o=1;o<=t;o++)
    {
        cin>>m>>n>>k;
        ll s=gcd(m,n);
        if(m>n) swap(m,n);
         minn=m/s; maxx=n/s;
        if(n%m>s) k--;
        if(minn*k>=maxx) cout<<"OBEY"<<endl;
        else cout<<"REBEL"<<endl;
    }
}
//0   7  "14  21"  28  35
//0     11      22   33
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}

6.Educational Codeforces Round 77 (Rated for Div. 2) B
在这里插入图片描述
题意:给定a,b两个值,变换规则是一个数减去一个值,另一个就得减去两倍的这个数(只能减),求经变换后能否使a,b同时为0。
  乍一看不好做,但慢慢写出来,假设两个数是m,n,使m减去某些数如:m–a-2b-2c-d=0,那么n-2a-b-c-2d=0。如此就完全可以发现,m的-a-d正好对应n的-2a-2d,剩下的同样,如此将这些多项式看作一个整体,就能够得到m=(a+b)+2*(c+d);n=(c+d)+2*(a+b);继而求得(a+b)和(c+d)的值分别为(2m-n)/3和(2n-m)/3,只要保证两个多项式的值是非负整数即可。

#include<iostream>
#include<iomanip>
#include<fstream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<cstdio>
#include<map>
#include<vector>
#include<ostream>
#include<istream>
typedef long long ll;
using namespace std;
#define mod 100000
#define PI acos(-1.0)
const ll maxn=200000;
ll n,m,k,a[20000],ans,aans,step;

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(0);
    int t;
    cin>>t;
    for(int o=1;o<=t;o++)
    {
        cin>>m>>n;
        if((2*n-m)%3==0&&2*n>=m&&(m*2-n)%3==0&&2*m>=n) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

感想:除了前面简单题,后面的自己做都很难想出来,其实很多的算法知识都是学过或者了解的,但确实,看到这个题目,不知道这个题要用某个算法解或者说总是不知道用哪个算法可以解出来,这应该才是所谓的出思路的能力吧。自认为自己应该更擅长出思路,其实只是还没碰到真正考验思维能力的题目。所以后的题目基本都是看过很多人的题解后借鉴或者照搬的别人的程序,将人家的思路实现或者把人家实现的代码拿过来研究一下怎么做出来的。而我自己都明白我做题时在代码实现上总会出问题,所以再看读题意。通常题目都会放在某一个场景下比如D题士兵的那个,这样会出现很多相关场景的单词增加理解难度,所以要不时的查单词甚至句子,如此看来,我也不敢说我在理解题意方面有多优秀了,所以好像啥都干不了了。不过,鉴于士兵的这个题目,我想到,或许培养一下翻英汉词典的速度或许很有用,正式的比赛只允许带纸质材料,如果可以,翻词典翻得快或许也有特殊的作用呢。。。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值