题目链接:http://codeforces.com/contest/948
A. Protect Sheep
题目大意:在一个R*C的农场里,每个格子可能是羊('S'),狼('W'),草('.'),狼可以向上、下、左、右四个方向走去吃羊,现在要在农场的草地上放置狗('D')来阻隔狼吃羊(如果一个格子上是狗的话,那么狼就无法走这个格子),现在要你验证是否可以通过放置一些狗来保证所有的羊都不被狼吃掉,并输出放置狗之后的农场的图;
题目思路:如果是要求放置最少的狗的话就有些难度,但题目说了并不要求令狗的数量最少,那这个就是个水题了,只要对每只羊进行一次判断,看这只羊上下左右四个方向是不是和狼直接相连,如果不相连,那就把这四个方向所有的草地都放上狗就行了。
AC代码如下:
#include <bits/stdc++.h>
using namespace std;
const int MX=505;
int R,C;
char mp[MX][MX];
int to[4][2]={0,1,0,-1,1,0,-1,0};
bool check(int x,int y){
bool flag=true;
for(int i=0;i<4;i++){
int nx=x+to[i][0],ny=y+to[i][1];
if(nx<0||nx>=R||ny<0||ny>=C) continue;
if(mp[nx][ny]=='W'){
flag=false;
break;
} else{
if(mp[nx][ny]!='S')
mp[nx][ny]='D';
}
}
return flag;
}
int main(){
scanf("%d%d",&R,&C);
for(int i=0;i<R;i++)
scanf("%s",mp[i]);
int flag=1;
for(int i=0;i<R;i++){
for(int j=0;j<C;j++){
if(mp[i][j]=='S')
if(!check(i,j)){
flag=0;
break;
}
}
}
if(!flag)
puts("No");
else{
puts("Yes");
for(int i=0;i<R;i++)
printf("%s\n",mp[i]);
}
return 0;
}
B. Primal Sport
题目大意:有一列数满足以下条件:对于Xi-1和Xi,Xi是满足被p整除同时大于等于Xi-1的最小值,(p为小于X-1的素数)同时Xi-1不被p整除,现在给出X2的值,要你求出满足上述条件最小的X0(X0>=3);
题目思路:既然X2满足被某个素数p整除,那么我们就可以对X2进行分解,求出X2所有的素因子,因为要使X0的值最小,那么X1的值也应该是最小的,因为X2是在[X1,X2]区间内唯一一个可以被p整除的,那么X1的取值范围就是[X2-p+1,X2],要使X1尽可能的小,那么就是得令p尽可能大,那就取X2最大的素因子就行,接着再求出X1的最大素因子,就可以推出相应的X0了,因为要求最小的X0,那么就把X1所有可能的取值枚举一遍,求出最小的X0即可。
AC代码如下:
#include <bits/stdc++.h>
using namespace std;
const int MX=1000+7;
const int INF=0x3f3f3f3f;
bool vis[MX];
int prime[MX],pcnt;
void init(){
for(int i=2;i<MX;i++){
if(!vis[i]){
prime[++pcnt]=i;
for(int j=2*i;j<MX;j+=i)
vis[j]=1;
}
}
}
int get_prime(int x){
int res=0;
for(int i=1;i<=pcnt&&prime[i]*prime[i]<=x;i++){
if(x%prime[i]==0){
res=max(prime[i],res);
while(x%prime[i]==0){
x/=prime[i];
}
}
}
if(x!=1)
res=max(x,res);
return res;
}
int main(){
init();
int x2;
cin>>x2;
int p1=get_prime(x2),x0=INF;
for(int x1=x2-p1+1;x1<=x2;x1++){
int p2=get_prime(x1);
int k=x1-p2+1;
if(k<=p2) continue;
x0=min(k,x0);
}
cout<<x0<<endl;
return 0;
}
C. Producing Snow
题目大意:Alice很喜欢堆雪堆,每天都会堆一个体积为Vi的雪堆,但由于天气太热了,每个雪堆每天都会融化掉Ti,一但一个雪堆融化完了就不会继续融化了,现在要你求出每天会融化掉多少体积的雪;
题目思路:雪堆融化的情况我们可以分为两种:
1、第 j 堆雪在第 i 天剩余的体积大于等于Ti,那么这堆雪融化掉的体积便为Ti;
2、第 j 堆雪在第 i 天剩余的体积小于Ti,那么这堆雪融化掉的体积便为第 j 堆雪的体积Vj;
本题我们可以用一个优先队列来维护在第 i 天时前 i 堆雪剩余的体积,但如果要每天都对每一个雪堆更新一次体积的话,时间复杂度是会爆炸的,在这题我们可以反过来维护,我们先用一个前缀和sum[i]来维护第 j 个雪堆前 i 天总共会融化掉多少雪,这时再来判断这堆雪的体积是否大于sum[i],如果小于sum[i]那么在第 i 天的时候就会完全融化完了,由于第 j 个雪堆在前 j-1 天里是没有融化的,那么我们就可以把第j个雪堆的体积加上sum[j-1],这样就可以直接与sum[i]进行比较了,每次将优先队列中小于等于sum的雪堆弹出,再把新的雪堆加入,一直维护雪堆融化的两种情况即可,具体实现看代码吧。
AC代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MX=1e5+7;
int n;
LL v[MX];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&v[i]);
priority_queue<LL,vector<LL>,greater<LL>>q;
LL t,e=0,sum=0,ans=0;
for(int i=1;i<=n;i++){
scanf("%lld",&t);
ans=0;
v[i]+=sum;
sum+=t;
q.push(v[i]);
while(!q.empty()&&q.top()<=sum){
ans+=q.top()+(sum-t);
q.pop();
e++;
}
printf("%lld ",ans+(i-e)*t);
}
printf("\n");
return 0;
}