【CF #776 div3】A-D

A. Deletions of Two Adjacent Letters

题目

分析

在所给字符串中查找求字符出现位置,从0开始存,奇数出现不可能通过操作留下所求字符,当然字符串中无所求字符也不可能。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=2e5+10;
const ll mod=-1e9+7;
const double pi=acos(-1);
int a[maxn],b[maxn];

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		string s;
		char c;
		cin>>s>>c;
		int f=0;
		for(int i=0;i<s.size();i++)
		{
			if(s[i]==c&&i%2==0)
			{
				cout<<"YES"<<endl;
				f=1;
				break;
			}
		}
		if(!f) cout<<"NO"<<endl;
	}
	return 0;
}

B. DIV + MOD

题目

分析

错误思路

判断所给范围r是否可被a整除,如果可以被a整除,最大值则在r或者r-1处取(一开始没有想到可直接在r-1处取值,还写了一个循环求,很明显会TLE)。如果无法整除,即将区间分为两段,以距离r最近的可被整除的数t为分界,两端分别求最大值,第一段最大值在t-1处取,第二段最大值在r处取,两段值进行比较。

正确思路

想复杂了,其实最大值就两种可能,一种在r-1处,另一种在r/a*a-1处(注意r/a*a-1与r-1的区别,他俩不相等!!就是这个地方没有考虑到)

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=2e5+10;
const ll mod=-1e9+7;
const double pi=acos(-1);

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int l,r,a;
		cin>>l>>r>>a;
		int t;
		int ans=r/a+r%a;
		t=r/a*a-1;
		cout<<t<<endl;
		if(t>=l) ans=max(ans,t/a+t%a);
		cout<<ans<<endl;
	}
	return 0;
} 

C. Weight of the System of Nested Segments

题目

分析

题意有一些难理解,不过读懂题之后,两个排序就可以解决这个问题了。

题目是说给m个点,分为n段,这n段之间不能有交叉,并且权值最小,求分段方式和这个系统的权值。

只需要先将所给点按照每个点的权值进行降序排序,选出所需要的点,并记录权值。再将所选出的点按照坐标位置排序,最后输出按坐标位置排序好后的输入序号。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=2e5+10;
const ll mod=-1e9+7;
const double pi=acos(-1);
struct node{
	int x,i,w;
}a[maxn],b[maxn];

bool cmp1(node a,node b)
{
	return a.w<b.w;
}

bool cmp2(node a,node b)
{
	return a.x<b.x;
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,m;
		int ans=0;
		cin>>n>>m;
		for(int i=1;i<=m;i++)
		{
			cin>>a[i].x>>a[i].w;
			a[i].i=i;
		}
		sort(a+1,a+m+1,cmp1);
		for(int i=1;i<=n*2;i++)
		{
			b[i]=a[i];
			ans+=a[i].w;
		}
		sort(b+1,b+2*n+1,cmp2);
		cout<<ans<<endl;
		for(int i=1;i<=n;i++)
		{
			cout<<b[i].i<<" "<<b[2*n-i+1].i<<endl;
		}
	}
	return 0;
} 

D. Twist the Permutation

题目

分析

给一个包含n个元素的数组,是[ 1, 2, 3, 4, 5, …, n ],可以做n次操作,第 i 次操作可以将前 i 个元素循环右移任意个位置。给你一个目标数组,问,在第 i 次操作中需要对元素循环右移多少位。输出第 i 次需要循环右移的次数。

我们使用逆向思维,反过来想这个问题。第 i 次的变化是不会影响到 i + 1及以上的数字的,所以数字n一定是最后一次变化从n号的位置一次变化到所给的数组的位置。这样就可以确定最后一位循环右移了多少位。具体看注释。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=2e5+10;
const ll mod=-1e9+7;
const double pi=acos(-1);
int a[maxn],b[maxn];

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			int t;
			cin>>t;
			a[t]=i;    // 记录每个数的最后位置
		}
		for(int i=n;i>0;i--)
		{
			/*
            计算出从原来的位置循环了几次,如i = 6, 假设a[i] = 4,
            则a[i] % i = 4 % 6 = 4 次
           */
			b[i]=a[i]%i;    
			for(int j=1;j<i;j++)
			{
				a[j]=(a[j]+i-b[i])%i;      // 这里是还原操作
			}
			/* 
                (i - b[i]) 实则是还原位置的次数,如i = 6, a[i] = 4, 那么需要6 - 4 = 2次
                即a = a + 2 = 4 + 2 = 6, 完成还原
            */
		}
		for(int i=1;i<=n;i++)
		{
			cout<<b[i]<<" ";
		}
		cout<<endl;
	}
	return 0;
} 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值