A. Compare T-Shirt Sizes
给出衣服尺码,判断两个尺码的大小关系。
思路:模拟。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
const int N=2e5+5;
int t;
std::string a,b;
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin>>t;
while(t--){
std::cin>>a>>b;
int lena=a.length(),lenb=b.length();
if(a==b){
std::cout<<'='<<'\n';
}
else if(a[lena-1]==b[lenb-1]&&a[lena-1]=='S'){
if(lena>lenb){
std::cout<<'<'<<'\n';
}
else if(lena==lenb){
std::cout<<'='<<'\n';
}
else if(lena<lenb){
std::cout<<'>'<<'\n';
}
}
else if(a[lena-1]==b[lenb-1]&&a[lena-1]=='L'){
if(lena>lenb){
std::cout<<'>'<<'\n';
}
else if(lena==lenb){
std::cout<<'='<<'\n';
}
else if(lena<lenb){
std::cout<<'<'<<'\n';
}
}
else{
if(a[lena-1]=='L'&&(b[lenb-1]=='M'||b[lenb-1]=='S')||a[lena-1]=='M'&&b[lenb-1]=='S'){
std::cout<<'>'<<'\n';
}
else if(b[lenb-1]=='L'&&(a[lena-1]=='M'||a[lena-1]=='S')||b[lenb-1]=='M'&&a[lena-1]=='S'){
std::cout<<'<'<<'\n';
}
}
}
return 0;
}
B. Funny Permutation
给出一个数字n,构造一个大小为n的permutation,使得对于每个位置i,都满足p[i]!=i且每个数相邻的数至少有一个数p[i]-1或p[i]+1。
思路:把顺序序列从中间截断,按顺序依次递增输出即可。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
const int N=2e5+5;
int t,n;
int a[N];
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin>>t;
while(t--){
std::cin>>n;
if(n==3){
std::cout<<-1<<'\n';
continue;
}
int pos=(n+1)/2;
for(int i=pos+1;i<=n;i++){
std::cout<<i<<' ';
}
for(int i=1;i<=pos;i++){
std::cout<<i<<' ';
}
std::cout<<'\n';
}
return 0;
}
os:还搞了好几次WA1,乐
C. Minimize the Thickness
给出一个数组,将它分成若干子数组,使得每个子数组的和都相等,对于同一个和,最小化所有段的最大值 。
思路:前缀和,枚举每个全部数之和的因数的前缀和,不断更新满足条件的答案。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
#define int long long
const int N=2e3+5;
int t,n;
ll a[N],dif[N];
signed main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin>>t;
while(t--){
std::cin>>n;
std::vector<ll>vec;
for(int i=1;i<=n;i++){
std::cin>>a[i];
dif[i]=dif[i-1]+a[i];
}
for(int i=1;i<=n;i++){
if(dif[n]%dif[i]==0){
vec.push_back(dif[i]);
}
}
int ans=1e9;
int len=vec.size();
for(int i=0;i<len;i++){
int pos=0,dis=-1;
for(int j=1;j<=n;j++){
if(dif[j]-dif[pos]==vec[i]){
dis=std::max(dis,j-pos);
pos=j;
}
}
if(pos==n) ans=std::min(ans,dis);
}
std::cout<<ans<<'\n';
}
return 0;
}
os:注意枚举因数的时候,是每个段之间的差都是这个因数。一开始我想成整除即可,WA两发,sad。
D. Masha and a Beautiful Tree
给出一个有2^n个数的permutation数组,分别位于n层满二叉树的叶节点。每次操作可以交换一个根节点的两个子树,问最少能通过几次操作使得数组有序,或者无法操作使得有序,输出-1。
思路: (1)归并:判断需要操作的位置和-1一样是判断区间边界的大小,具体看代码;
(2)DFS搜索:每次搜索两半数组的范围,注意判断条件是对于一段最左侧最右侧的值进行判断,判-1的条件是对于一个区间排序完成后最小值和最大值的计算。
AC Code:
(1)
#include <bits/stdc++.h>
typedef long long ll;
const int N=262144+5;
int t,n,ans;
int a[N],tmp[N];
bool flag;
void merge_sort(int a[],int l,int r){
if(l>=r) return;
int mid=(l+r)>>1;
merge_sort(a,l,mid);
merge_sort(a,mid+1,r);
int k=0,i=l,j=mid+1;
while(i<=mid&&j<=r){
if(a[i]<a[j]) tmp[++k]=a[i++];
else tmp[++k]=a[j++];
}
if(i==l) ans++;
if(i!=l&&j!=mid+1) flag=true;
while(i<=mid) tmp[++k]=a[i++];
while(j<=r) tmp[++k]=a[j++];
for(int i=l,j=1;i<=r;j++,i++) a[i]=tmp[j];
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin>>t;
while(t--){
memset(a,0,sizeof(a));
memset(tmp,0,sizeof(tmp));
std::cin>>n;
for(int i=1;i<=n;i++){
std::cin>>a[i];
}
ans=0;
flag=false;
merge_sort(a,1,n);
if(flag) std::cout<<-1<<'\n';
else std::cout<<ans<<'\n';
}
return 0;
}
(2)
#include <bits/stdc++.h>
typedef long long ll;
const int N=262144+5;
int t,n,ans;
int a[N];
bool flag;
void getans(int l,int r){
if(l==r) return;
int mid=l+r>>1;
int len=r-l+1>>1;
getans(l,mid);
getans(mid+1,r);
if(a[l+len]<a[l]){
ans++;
std::swap(a[l],a[l+len]);
}
if(a[l]+len!=a[l+len]) flag=true;
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin>>t;
while(t--){
std::cin>>n;
flag=false;
ans=0;
for(int i=1;i<=n;i++){
std::cin>>a[i];
}
getans(1,n);
if(flag) std::cout<<-1<<'\n';
else std::cout<<ans<<'\n';
}
return 0;
}
E. Sending a Sequence Over the Network
对于一个数组a,我们可以把它划分为若干段,例如a=[1,2,3,1,2,3],我们可以把它划分为[1],[2,3,1],[2,3]三段,将他们和他们的长度重新组合,要求每段长度可以在这一段左侧或是右侧,这样对于一个相同的划分方式,最后得到的可能有若干种结果。现给出这个最终结果,判断是否存在一个原数组,使得操作后成为现在给出的数组。
思路:对于可行性进行DP。定义f[i]为前i个数是否存在合法序列,对于每一个数a[i],都有可能是某一段的最左侧数字或最右侧数字,分情况即可。
AC Code:
#include <bits/stdc++.h>
typedef long long ll;
const int N=2e5+5;
int t,n;
int a[N],f[N];
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
std::cin>>t;
while(t--){
std::cin>>n;
for(int i=1;i<=n;i++){
std::cin>>a[i];
f[i]=0;
}
f[0]=1;
for(int i=1;i<=n;i++){
if(i+a[i]<=n)
f[i+a[i]]|=f[i-1];
if(i>=a[i]+1)
f[i]|=f[i-a[i]-1];
}
if(f[n]) std::cout<<"YES"<<'\n';
else std::cout<<"NO"<<'\n';
}
return 0;
}
F. Multi-Colored Segments
待补。