A. Circle Coloring
签到,abc三个数组找到一个符合要求的就行了
#include <bits/stdc++.h>
using namespace std;
int a[105],b[105],c[105];
int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=1;i<=n;i++)cin>>c[i];
int last=a[1];
cout<<last<<' ';
for(int i=2;i<=n-1;i++){
if(a[i]!=last)cout<<a[i]<<' ',last=a[i];
else if(b[i]!=last)cout<<b[i]<<' ',last=b[i];
else if(c[i]!=last)cout<<c[i]<<' ',last=c[i];
}
if(a[n]!=a[1]&&a[n]!=last)cout<<a[n];
else if(b[n]!=a[1]&&b[n]!=last)cout<<b[n];
else if(c[n]!=a[1]&&c[n]!=last)cout<<c[n];
cout<<endl;
}
}
B. Arrays Sum
想了挺久的B
发现一个b能够消掉不同的k-1个数字(另一个为0)
不过要记得特判一下 c n t = 1 cnt=1 cnt=1的情况以及保证 a n s > = 1 ans>=1 ans>=1
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main(){
int t;cin>>t;
while(t--){
int n,k;cin>>n>>k;
set<int>q;
for(int i=1;i<=n;i++){
cin>>a[i];
q.insert(a[i]);
}
int cnt=q.size();//统计有几个不同的数字
if(k==1){
if(cnt==1)cout<<1<<endl;
else cout<<-1<<endl;
continue;
}
int ans;
if((cnt-1)%(k-1)==0)ans=(cnt-1)/(k-1);
else ans=(cnt-1)/(k-1)+1;
cout<<max(1,ans)<<endl;//这里大概是赛后fst的点?
}
}
C. Discrete Acceleration
就模拟,也发现有二分时间的做法
由于比赛时变量定义太混乱,就不上代码了
D. Searchlights
看错了n和m的数据范围,还以为是1e6的,在想怎么用O( n l o g n nlogn nlogn)做,实际上最大只有2000
根据题意,强盗必须在x和y至少一个方面大于探照灯which means 如果 x < = c j − a i x<=c_j-a_i x<=cj−ai,那么 y > = d j − b i + 1 y>=d_j-b_i+1 y>=dj−bi+1
因为上界不大,因此我们用f数组的下标存每个x的位置,让其等于y的最小值,即 f ( c j − a i ) = m a x ( f ( c j − a i ) , d j − b i + 1 ) f_(c_j-a_i)=max(f_(c_j-a_i) , d_j-b_i+1) f(cj−ai)=max(f(cj−ai),dj−bi+1),所以用O( n m nm nm)处理
最后f数组记录后缀的最大值,然后加上向右需要移动的距离求个最小值
为什么是求后缀的最大值呢,比如对于 1 < x < C 1<x<C 1<x<C,1到x-1的这段只需要向右移动x就行,x到C的这段需要向上移动,向上移动的距离就是x到C每个点需要移动的最大值,所以是记录后缀的最大值
时间复杂度 O ( n m + C ) O(nm+C) O(nm+C)
#include <bits/stdc++.h>
using namespace std;
int a[2005],b[2005],c[2005],d[2005],f[2000005];
int main(){
int n,m;cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i]>>b[i];
for(int i=1;i<=m;i++)cin>>c[i]>>d[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i]<=c[j]){
f[c[j]-a[i]]=max(f[c[j]-a[i]],d[j]-b[i]+1);
}
}
}
int ans=2000000+2;
int maxs=0;
for(int i=1000001;i>=0;i--){
maxs=max(maxs,f[i]);
ans=min(ans,i+maxs);
}
cout<<ans<<endl;
}
再给一个二分的做法
#include <bits/stdc++.h>
using namespace std;
int a[2005],b[2005],c[2005],d[2005],f[2000005];
int n,m;
bool check(int mid){
for(int i=0;i<=mid;i++)f[i]=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int sum=c[j]+d[j]-a[i]-b[i]-mid;
if(a[i]<=c[j]&&b[i]<=d[j]&&sum>=0){
f[max(0,c[j]-a[i]-sum)]++;
f[c[j]-a[i]+1]--;
}
}
}
for(int i=1;i<=mid;i++)f[i]+=f[i-1];
for(int i=0;i<=mid;i++)if(f[i]==0)return 1;
return 0;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i]>>b[i];
for(int i=1;i<=m;i++)cin>>c[i]>>d[i];
int l=0,r=2e6,ans=0;
while(l<=r){
int mid=(l+r)/2;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;
}
剩余待补题完写