A. Planets
卫星射击,简单的模拟题
#include<bits/stdc++.h>
using namespace std;
int a[105];
int main()
{
int t;cin>>t;
while(t--){map<int,int>mp;
int n,c;cin>>n>>c;
for(int i=0;i<n;i++){cin>>a[i];、mp[a[i]]++;}
int ans=0;
for(auto i:mp)
if(i.second>=c)ans+=c;
else ans+=i.second;
cout<<ans<<endl;
}
return 0;
}
B. Meeting on the Line
题意:每个人到 x0 的所花时间是 ti +| x0 - xi |,求应该把x0设置在哪里
思路:
二分时间,并且check 时间是否合适。最后得到合适的最短时间,用这个最短时间去找每个人能够移动的最大范围的重叠的地方,那么这个重叠的地方就是答案。同时关于怎么check也是找区间,有过有的区间没有重叠的地方,那么这个时间就是不合适的了。
注意:
记得在输出的时候要输出10位,不然会WA
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
double x[100005],t[100005],n,ans;
bool check(double mid){
double r=1e18,l=0;
for(int i=0;i<n;i++){
if(mid<t[i])return 0;
double time=mid-t[i];
r=min(r,x[i]+time);
l=max(l,x[i]-time);
}
ans=r;
return r>=l;
}
signed main()
{
int T;cin>>T;
while(T--){
cin>>n;
for(int i=0;i<n;i++)cin>>x[i];
for(int i=0;i<n;i++)cin>>t[i];
double l=0,r=1e18;//模拟时间
for(int i=1;i<=100;i++){
double mid=(l+r)/2;
if(check(mid)){r=mid;}
else l=mid;
}
check(r);
cout<<fixed<<setprecision(10)<<ans<<endl;
}
return 0;
}
C. Minimum Notation
简单模拟
思路:记录最终输出的答案的0~9的个数,之后从小到大输出
1.把每个数的位置记录下来,从0到9枚举 i 的最后一位
2.之后把从i-1的最后一位到 i 的最后一位中间的数记录
2.1 如果是数字是9,9的个数+1
2.2如果是数字是i,i的个数+1
2.3剩下情况,(该数字+1)的个数+1
之后从小到大输出
代码:
#include<bits/stdc++.h>
using namespace std;
char s[200005],ss[200005];
int main()
{
int T;cin>>T;
while(T--){
cin>>s;
vector<int>v[10];
int co[10]={0};
int n=strlen(s);
for(int i=0;i<n;i++){
ss[i]=s[i];
v[s[i]-'0'].push_back(i);
}
int l=0;
for(int i=0;i<=9;i++){
int r=v[i].size();
if(r==0)continue;
if(v[i][r-1]<l)continue;
for(int q=l;q<=v[i][r-1];q++){
if(s[q]==(i+'0'))co[i]++;
else if(s[q]=='9')co[9]++;
else co[s[q]-'0'+1]++;
}
l=v[i][r-1]+1;
}
for(int i=0;i<=9;){
if(co[i]!=0)cout<<i;co[i]--;if(co[i]<=0)i++;
}
cout<<endl;
}
return 0;
}
D. Prefixes and Suffixes(字符串构造)
题意:有两个字符串s和t,交换同等长度的s的前缀和t的后缀,问能否使s等于t?
(虽然下面的预备知识是另一种方法,但我没有学会……)
预备知识:next数组代表了最长公共前缀和,即(除了当前字符)前缀(从左往右)和后缀(从左往右)的最长的公共长度,next[i]-1就是这个长度(如果最前面的那个是0的话);如果最前面的next值是-1的话,next记录的就是最长的公共长度。
如下面的例子:next数组求解详解
模式串 | a | b | a | b | a | a | a | b | a | b | a | a |
---|---|---|---|---|---|---|---|---|---|---|---|---|
下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
next数组 | 0 | 1 | 1 | 2 | 3 | 4 | 2 | 2 | 3 | 4 | 5 | 6 |
void getnx(string &t,int *nx){
for(int i=1,j=0;i<(int)t.size();i++){ //j记录每次nx[]的长度 i从1, j从0开始
while(j&&t[i]!=t[j])
j=nx[j-1];
if(t[i]==t[j])j++;
nx[i]=j;
}
}
思路:参考D. Prefixes and Suffixes(字符串/思维/回文串)
设字符串下标从0开始,len=s.size()
从交换中可以看到s1[i]和s2[len-i-1]的相对位置都是不变的,例如下图{b, 2}的相对位置就是不变的,都是对称的
因此如果某一对是偶数次,那么符合题意
如果某一对是奇数次,
如果两个字符不同的话,那一定是不行的
如果是一样的话,只有一次可以,就是中间的时候
代码:
#include<bits/stdc++.h>
using namespace std;
string s1,s2;
map< pair<char,char>,int>mp;
int main()
{
int T;cin>>T;
while(T--){
mp.clear();int n;cin>>n;
cin>>s1>>s2;
for(int i=0;i<n;i++){
char a=s1[i],b=s2[n-i-1];
if(a>b)swap(a,b);
mp[{a,b}]++;
}
int qi=0;bool flag=1;
for(auto i:mp){
if(i.second%2==0)continue;
if(i.first.first!=i.first.second){flag=0;break;}
else{qi++;if(qi>1){flag=0;break;}}
}
if(flag)cout<<"YES\n";
else cout<<"NO\n";
}
return 0;
}