Codeforces Global Round 10题解(A-D)
A. Omkar and Password
题目:http://codeforces.com/contest/1392/problem/A
题解:看似觉得有些难手,但是仔细思考下就会发现,只要整个数组中有1个与其它不一样,那么最终都会合成为1个数字,只有全部一样的数字才不能合成。
代码:
#include<bits/stdc++.h> //POJ不支持
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 200010;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
int main()
{
IOS;
ll t,n;
cin>>t;
while(t--)
{
cin>>n;
ll i,x;
bool flag=false;
ll sum=0;
for(i=1;i<=n;i++)
{
cin>>x;
if(i==1)
sum=x;
if(i!=1&&x!=sum)
flag=true;
}
if(flag==true)
cout<<"1"<<endl;
else
cout<<n<<endl;
}
return 0;
}
B. Omkar and Infinity Clock
题目:http://codeforces.com/contest/1392/problem/B
题解:这是一道很简单的数组的值变化问题,最终只会有两组数组出现,只要根据K的奇偶性,来判断应该输出哪组数组即可
代码:
#include<bits/stdc++.h> //POJ不支持
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 200010;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
ll a[maxn],b[maxn];
int main()
{
ll t,n,k;
ll i,j;
cin>>t;
while(t--)
{
cin>>n>>k;
ll m=-1000000000;
for(i=1;i<=n;i++)
{
cin>>a[i];
m=max(m,a[i]);
}
ll f=-1000000000;
for(i=1;i<=n;i++)
{
a[i]=m-a[i];
f=max(f,a[i]);
}
for(i=1;i<=n;i++)
{
b[i]=f-a[i];
}
if(k%2==1)
{
for(i=1;i<=n;i++)
{
if(i!=1)
cout<<" "<<a[i];
else
cout<<a[i];
}
}
else
{
for(i=1;i<=n;i++)
{
if(i!=1)
cout<<" "<<b[i];
else
cout<<b[i];
}
}
cout<<endl;
}
return 0;
}
C. Omkar and Waterslide
题目:http://codeforces.com/contest/1392/problem/C
题解:一开始设想的是从前往后找,发现要考虑的东西太多了,之后看了看别人的代码后,发现从后往前找就非常的简单了,只要当前的数比前一个小,就一直加到前一个数一样大;如果比他小,就继续比较那个数与他前面的数进行比较。最终得到的一定是一个单调不递减数组,并且操作次数也是最少的
代码:
#include<bits/stdc++.h> //POJ不支持
#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 200010;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
ll a[maxn];
int main()
{
IOS;
ll i,j,t,n;
cin>>t;
while(t--)
{
cin>>n;
ll ans=0;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=n;i>=2;i--)
{
if(a[i]<a[i-1])
ans+=a[i-1]-a[i];
}
cout<<ans<<endl;
}
return 0;
}
D. Omkar and Bed Wars
题目:http://codeforces.com/contest/1392/problem/D
题解:
首先我们现将环破成链,然后对他进行分析。
共有两种情况:其一为全部是L或全部是R,对于这种情况分三种讨论,当n小于等于2时,输出0;当n==3时,输出1;当n大于3时,输出n/3+(n%3>0)即可
其二就是有L也有R,根据第一步我们找到对应的flag为断点,将环变成链,然后我们首先找到连续相同字母出现的次数进行统计,他们的最少变化次数是cnt/3,因此我们只需要找出在最终形成的链中,相同字母出现的次数/3,累加即可。
这里切记注意,flag要用tmp替换一下,因为在for循环里i<n+flag,其中的flag如果不进行替换,那么下面的flag移动,上面循环里的也会变化,因此注意!!
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=4e5+10; ll n; char s[maxn]; int main() { int t,i; cin>>t; while(t--) { ll ans=0; cin>>n; scanf("%s",s); for(i=0;i<n;i++) s[i+n]=s[i]; int flag=-1; for(i=0;i<n;i++) { if(s[0]!=s[i]) { flag=i; break; } } if(flag==-1) { if(n<=2) cout<<"0"<<endl; else if(n==3) cout<<"1"<<endl; else { cout<<n/3+(n%3>0)<<endl; } } else { ll cnt=0; ll tmp=flag; for(i=flag;i<n+flag;i++) { if(s[i]==s[tmp]) cnt++; else { ans+=cnt/3; tmp=i; cnt=1; } } ans+=cnt/3; cout<<ans<<endl; } } return 0; }