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;
}