题目网址:http://codeforces.com/contest/1015
1、D题
题意:给一个n,k,sn,k,s代表现在有nn个房子,你需要搬家kk次,搬家的总的距离为ss。每次搬家的距离定义为|x−y||x−y|(x,y为第几个房子),让你构造一个转移序列,满足正好为kk次,总距离为ss.
首先我们判断:
- s<ks<k时一定构造不出来
- k∗(n−1)<s k∗(n−1)<s时也构造不出来
对于其他情况,一定可以构造,我们每次转移的距离选择s-k
和n-1
中比较小的那一个,然后总距离减去走的距离,当当前走的距离加上转移的距离大于n
的时候,就要往回走,然后一直走下去,就可以构造出来序列了。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
#define MAX 200005
int ans[MAX];
ll n,k,s;
int main()
{
cin>>n>>k>>s;
if((n-1)*k<s||s<k)
{
cout<<"NO"<<endl;
return 0;
}
cout<<"YES"<<endl;
int pos=1;
for(int i=1;i<=k;i++)
{
ll cnt=k-i;
ll sum=min(n-1,s-cnt);
s-=sum;
if(pos+sum<=n) pos+=sum; else pos-=sum;
ans[i]=pos;
}
for(int i=1;i<=k;i++)
cout<<ans[i]<<" ";
cout<<endl;
}
2、E1题
题解:题目给出如何判定一个星星的标准,请你找出有多少个星星
这题可以先预处理四个数组去记录左右上下的 星号个数,然后找星星时找最小值就行,输出用结构体记录
复杂度:O( N*M*C) C为常数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mod 1000000007
#define MAX 105
char s[MAX][MAX],s2[MAX][MAX];
int u[MAX][MAX],b[MAX][MAX],l[MAX][MAX],r[MAX][MAX],len[MAX][MAX];
int n,m;
struct node{
int x, y, s;
node(){}
node(int nx, int ny, int ns){
x = nx, y = ny, s = ns;
}
} f[MAX*MAX];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>s[i]+1;
/*for(int i=1;i<=n;i++)
cout<<s[i]+1;*/
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='*')
l[i][j]=l[i][j-1]+1;
}
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
{
if(s[i][j]=='*')
r[i][j]=r[i][j+1]+1;
}
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
{
if(s[i][j]=='*')
u[i][j]=u[i-1][j]+1;
}
for(int j=1;j<=m;j++)
for(int i=n;i>=1;i--)
{
if(s[i][j]=='*')
b[i][j]=b[i+1][j]+1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
s2[i][j]='.';
/*for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cout<<b[i][j];*/
memset(len,0,sizeof(len));
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='*')
{
len[i][j]=min(u[i][j],min(b[i][j],min(l[i][j],r[i][j])));
len[i][j]--;
if(!len[i][j])
continue;
f[++cnt] = node(i, j, len[i][j]);
for(int k=i-len[i][j];k<=i+len[i][j];k++)s2[k][j]='*';
for(int k=j-len[i][j];k<=j+len[i][j];k++)s2[i][k]='*';
}
}
/*for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cout<<s2[i][j];*/
bool flag=true;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]!=s2[i][j])
flag=false;
if(!flag)cout<<"-1"<<endl;
else
{
cout<<cnt<<endl;
for(int i = 1; i <= cnt; i++){
printf("%d %d %d
", f[i].x, f[i].y, f[i].s);
}
}
return 0;
}
3、E2
题意:与上题一样,只不过数据从100到1000
当时上面的代码也是可以通过的,也可以做一个优化,就是再加两个数组,用类似区间求和的方法去标记星号的位置,让后就可以去掉s2,
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mod 1000000007
#define MAX 1005
char s[MAX][MAX];
int u[MAX][MAX],b[MAX][MAX],l[MAX][MAX],r[MAX][MAX],len[MAX][MAX],w[MAX][MAX],e[MAX][MAX];
int n,m;
struct node{
int x, y, s;
node(){}
node(int nx, int ny, int ns){
x = nx, y = ny, s = ns;
}
} f[MAX*MAX];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>s[i]+1;
/*for(int i=1;i<=n;i++)
cout<<s[i]+1;*/
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='*')
l[i][j]=l[i][j-1]+1;
}
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
{
if(s[i][j]=='*')
r[i][j]=r[i][j+1]+1;
}
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++)
{
if(s[i][j]=='*')
u[i][j]=u[i-1][j]+1;
}
for(int j=1;j<=m;j++)
for(int i=n;i>=1;i--)
{
if(s[i][j]=='*')
b[i][j]=b[i+1][j]+1;
}
/*for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cout<<b[i][j];*/
memset(len,0,sizeof(len));
memset(w,0,sizeof(w));
memset(e,0,sizeof(e));
int cnt=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='*')
{
len[i][j]=min(u[i][j],min(b[i][j],min(l[i][j],r[i][j])));
len[i][j]--;
int t=len[i][j];
if(!len[i][j])
continue;
f[++cnt] = node(i, j, len[i][j]);
w[i][j-t]++,w[i][j+t+1]--;
e[i-t][j]++,e[i+t+1][j]--;
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
w[i][j]+=w[i][j-1],e[i][j]+=e[i-1][j];
bool flag=true;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='*'&&!w[i][j]&&!e[i][j])
flag=false;
if(!flag)cout<<"-1"<<endl;
else
{
cout<<cnt<<endl;
for(int i = 1; i <= cnt; i++){
printf("%d %d %d
", f[i].x, f[i].y, f[i].s);
}
}
return 0;
}
4、F题
这道过的人较少,以后再补