比赛链接:
http://codeforces.com/contest/1157
A. Reachable Numbers
模拟,用个vis记录下是否被访问就可以了
代码如下:
//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 10007;
const int maxn = 1e3+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
ll n;
map<ll,int>ma;
int main()
{
scanf("%lld",&n);
int num=1;
stack<ll>s;
s.push(n);
ma[n]=1;
while(!s.empty())
{
ll t=s.top();
s.pop();
t++;
while(t%10==0)
{
t/=10;
}
if(ma[t]==0)
{
ma[t]=1;
s.push(t);
num++;
}
}
printf("%d\n",num);
return 0;
}
B. Long Number
模拟,找到第一个f(x)>x的数,然后遍历下去,直到f(x)<x的数为止。
代码如下:
//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
char a[maxn];
int n;
int f[15];
int main()
{
scanf("%d",&n);
scanf("%s",a);
for (int i=1;i<=9;i++)
{
scanf("%d",&f[i]);
}
int st=0,ok=1;
while(a[st]>=(f[a[st]-'0']+'0')&&st<n)
{
st++;
}
while(a[st]<=(f[a[st]-'0']+'0')&&st<n)
{
a[st]=(f[a[st]-'0']+'0');st++;
}
printf("%s\n",a);
return 0;
}
C1. Increasing Subsequence (easy version)
贪心,如果左右两个数都比之前的数大,则找两个中较小的,如果两个数都小于之前的数则跳出,否则找其中较大的一个。
代码如下:
//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
int n;
int a[maxn];
vector<char>ans;
int b[maxn];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
b[0]=0;
int num=0;
int i=1,j=n;
while(i<=j)
{
if(max(a[i],a[j])<b[num])
{
break;
}
if((a[i]<a[j]&&a[i]>b[num])||a[j]<b[num])
{
ans.push_back('L');
b[++num]=a[i];
i++;
}
else
{
ans.push_back('R');
b[++num]=a[j];
j--;
}
}
printf("%d\n",ans.size());
for (int i=0;i<ans.size();i++)
{
printf("%c",ans[i]);
}
printf("\n");
return 0;
}
C2. Increasing Subsequence (hard version)
这个题在之前的基础上加了出现相同的数字,还是按上一题的贪心策略,只不过遇到相等的数字的时候只能连续选一边的,看看哪一边连续递增序列最长即可。
代码如下:
//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
int n;
int a[maxn];
vector<char>ans;
int b[maxn];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
b[0]=0;
int num=0;
int i=1,j=n;
int ok=0;
while(i<=j)
{
if(max(a[i],a[j])<=b[num])
{
break;
}
if(a[i]==a[j]&&i!=j)
{
ok=1;
break;
}
if((a[i]<a[j]&&a[i]>b[num])||a[j]<=b[num])
{
ans.push_back('L');
b[++num]=a[i];
i++;
}
else
{
ans.push_back('R');
b[++num]=a[j];
j--;
}
}
if(ok)
{
int num1=0,num2=0;
int ii=i,jj=j;
int ti=b[num],tj=b[num];
while(a[ii]>ti&&ii<j)
{
num1++;
ti=a[ii];
ii++;
}
while(a[jj]>tj&&jj>i)
{
num2++;
tj=a[jj];
jj--;
}
if(num1>num2)
{
for (int i=0;i<num1;i++) ans.push_back('L');
}
else
{
for (int i=0;i<num2;i++) ans.push_back('R');
}
}
printf("%d\n",ans.size());
for (int i=0;i<ans.size();i++)
{
printf("%c",ans[i]);
}
printf("\n");
return 0;
}
D. N Problems During K Days
先判定是否大于等于最小的情况。
然后在最小的情况下均分k个数,即每个数加上(n-(k*(k+1)/2))%k,然后在贪心把n%k加到k个数中,从后面往前面贪,遇到后面的数小于前面数的2倍就加上数使其等于前一个的数的二倍,如果n%k消耗完则符合要求,如果消耗不完则输出NO
代码如下:
//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
ll k;
ll n;
ll ans[maxn];
int main()
{
scanf("%lld%lld",&n,&k);
if(n<k*(1+k)/2)
{
printf("NO\n");
return 0;
}
n-=k*(1+k)/2;
ll t=n/k;
n=n%k;
for (int i=1;i<=k;i++)
{
ans[i]=i+t;
}
for (int i=k-1;i>=1;i--)
{
if(n==0) break;
if(ans[i]*2>ans[i+1])
{
ll cha=2*ans[i]-ans[i+1];
if(n>=cha)
{
ans[i+1]+=cha;
n-=cha;
}
else
{
ans[i+1]+=n;
n=0;
}
}
}
if(n==0)
{
printf("YES\n");
for (int i=1;i<=k;i++) printf("%lld ",ans[i]);
printf("\n");
}
else
{
printf("NO\n");
}
return 0;
}
E. Minimum Array
此题可以用mutliset容器来做,将所有的b[i]压入mutliset中,然后求出啊a[i]中的最优解,然后二分查找大于等于这个最优解的位置,如果没有找到的话,则直接用首部元素,因为这时候首部元素是最优解,找到之后再删除这个元素。
代码如下:
//include <bits/stdc++.h>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <time.h>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MOD = 10007;
const int maxn = 2*1e5+5;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
int n;
int a[maxn];
int b[maxn];
int ans[maxn];
multiset<int>st;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for (int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
st.insert(b[i]);
}
for (int i=1;i<=n;i++)
{
multiset<int>::iterator it;
int yu=(n-a[i])%n;
it=st.lower_bound(yu);
if(it==st.end())
{
it=st.begin();
ans[i]=(a[i]+(*it))%n;
st.erase(it);
}
else
{
ans[i]=(a[i]+(*it))%n;
st.erase(it);
}
}
for (int i=1;i<=n;i++)
{
printf("%d ",ans[i]);
}
printf("\n");
return 0;
}