Problem - A - Codeforces
思路:当且仅当y<=-2是追不上的。
void solve(){ A
int x,y; cin>>x>>y;
if(y<=-2) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
Problem - B - Codeforces
思路:因为不能破坏stra,所以只能在stra的左端或者右端添加字符,那么stra,strb相同的片段在strb中只能是连续的,不能拆开的,不然补不全。因此枚举strb连续的子串在stra中出现的最大长度即可。
void solve(){ B 写了44分钟。。stra,strb相同的片段在strb中只能是连续的,不能拆开的,不然是子序列也没用,补不全。 好好好...
stra为子串,strb为子序列
string stra,strb; cin>>stra>>strb;
int na=stra.size(),nb=strb.size();
int maxn=0;
for(int i=0;i<nb;i++){
int idx=i,cnt=0;
for(int j=0;j<na;j++){
if(stra[j]==strb[idx]) idx++,cnt++;
}
maxn=max(maxn,cnt);
}
cout<<na+nb-maxn<<endl;
}
Problem - C - Codeforces
思路:很明显的贪心。首先在1和0/-1之间,肯定先选1,在0和-1之间肯定先选0。当1和1,-1和-1,先记录下来,后面贪心再用。目标是让cura和curb尽量接近。所以like和hate是用来控制他们尽量接近的。要注意的是like==hate的时候,是不能跳过操作的。例如处理完输入完之后curb=100,cura=10,like=20,hate=20。这个时候hate大可以全给curb,like全给cura。这样可以得到ans=30。其他的情况也类似贪心即可。
int a[200005],b[200005];
void solve(){ C 贪心,注意细节
int n; cin>>n;
int cura=0,curb=0,like=0,hate=0;
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>>a>>b了。。
if(a[i]==1&&b[i]==1) like++;
else if(a[i]==-1&&b[i]==-1) hate++;
else if(a[i]==1) cura++;
else if(b[i]==1) curb++;
}
if(cura>curb) swap(cura,curb); cura<=curb
if(like>hate){
// like-=hate; 这样还不够贪心。如果dif很大很大,那么可以把hate给curb,like全给cura
int dif=curb-cura;
if(hate>=dif) curb=cura,hate-=dif; 尽量让cura==curb
else curb-=hate,hate=0;
like-=hate;
dif=curb-cura;
if(like>=dif) {
like-=dif,cura=curb;
cout<<cura+like/2<<endl;
}
else {
cura+=like;
cout<<min(cura,curb)<<endl;
}
}
else if(hate>like){
// hate-=like; 这样还不够贪心。如果dif很大很大,那么可以把hate给curb,like全给cura
int dif=curb-cura;
if(like>=dif) cura=curb,like-=dif; 尽量让cura==curb
else cura+=like,like=0;
hate-=like;
dif=curb-cura;
if(hate>=dif){
hate-=dif,curb=cura;
if(hate&1) cout<<cura-hate/2-1<<endl;
else cout<<cura-hate/2<<endl;
}
else cout<<cura<<endl;
}
else if(hate==like){
int dif=curb-cura;
if(hate>=dif/2) cura+=dif/2,curb-=dif/2;
else cura+=like,curb-=hate;
cout<<min(cura,curb)<<endl;
}
}
Problem - D - Codeforces
思路:排序+贪心。贪心地选dif更小的操作,输入时记录每一个dif,之后升序排序。要注意的是,暴力的跑是o(n*m)是肯定不行的。但是实际上同样数量的不同类型金属锭,是可以一起计算的。所以可以用一个桶cnt[i]来记录剩余数量为i的金属锭有几个。但是最大的金属锭数量是1e9,桶是不能记录的。但是最大的a只有1e6,所以可以记录小的mindif是多少,以及对应的a。在输入金属锭大小的时候,如果能冶炼金属a,那么直冶炼,这样保证所有金属锭数量<=1e6,桶是可以记录的。最后从1e6到1遍历cnt即可。
int n,m;
typedef struct node{
int a,b,dif;
bool operator < (const node &x) const{
if(dif!=x.dif) return dif<x.dif;
return a<x.a;
}
}node;
node arr[1000006];
int cnt[1000006];
void solve(){ D 排序+贪心
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>arr[i].a;
for(int i=1;i<=n;i++) {
cin>>arr[i].b;
arr[i].dif=arr[i].a-arr[i].b;
}
sort(arr+1,arr+n+1);
int ans=0,aa=arr[1].a,mindif=arr[1].dif;
for(int i=1;i<=m;i++){
int x; cin>>x;
if(x>=aa){
ans+=(x-aa)/mindif+1;
x=x-((x-aa)/mindif+1)*mindif;
}
cnt[x]++;
}
int idx=1;
for(int i=1e6;i>=1&&idx<=n;i--){
if(cnt[i]){
int x=i;
while(x<arr[idx].a&&idx<=n) idx++;
if(idx>n) break;
aa=arr[idx].a,mindif=arr[idx].dif;
ans+=((x-aa)/mindif+1)*cnt[i];
x=x-((x-aa)/mindif+1)*mindif;
cnt[x]+=cnt[i];
}
}
cout<<ans*2<<endl;
}