http://codeforces.com/contest/1153/problem/C
题意:给你由’(’ ,’)’,’?'组成的序列,问你能不能把?变成‘(’或‘)’,使它中间[1-L](1<=L<|s|)都是不合法的括号序列,而整个序列是合法的。
做法:先算出?一共可以填多少个左括号,用l表示当前已经有多少个左括号,用r表示当前有多少个右括号,以下几种情况都是不合题意的序列:
①第一个不是左括号,最后一个不是右括号
②填的过程中出现当前左括号数量小于等于右括号数量
③填完整个序列发现真正填的左括号数量小于应该填的左括号数量
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 300005;
char s[maxn],s1[maxn];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",s);
if(n%2)
{
printf(":(");
}
else
{
int num = n / 2;
int len = strlen(s);
for(int i=0; s[i] != '\0'; i++)
{
if(s[i] == '(')
num--;
}
int flag = 1;
if(s[0] == ')')
{
flag = 0;
}
else
{
int l=0,r=0;
for(int i=0; s[i] != '\0'; i++)
{
if(s[i] == '(')
{
s1[i] = '(';
l++;
}
if(s[i] == ')')
{
s1[i] = ')';
r++;
}
if(s[i] == '?')
{
if(num)
{
s1[i] = '(';
num--;
l++;
}
else
{
s1[i] = ')';
r++;
}
}
if(l <= r && i < len - 1)
{
flag = 0;
break;
}
}
if(num != 0 || s1[len-1] != ')')
flag = 0;
}
if(flag)
printf("%s",s1);
else
printf(":(");
}
}
http://codeforces.com/contest/1117/problem/A
题意:找算术平均值最大且最长的一段连续序列,输出长度
做法:平均值最大是第一条件,所以我们先找出数列中最大的那个数,然后看看它左右连续区间里有多少个和它相同的数,记录并比较最长长度就好了
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 100005;
int a[maxn];
int main()
{
int n;
scanf("%d",&n);
int mx = -INF;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
mx = max(mx,a[i]);
}
int ans = 0,sum = 0;
for(int i=1; i<=n; i++)
{
if(a[i] == mx)
{
sum++;
ans = max(ans,sum);
}
else
sum = 0;
}
printf("%d",ans);
}
http://codeforces.com/contest/1117/problem/B
题意:有n种方案,每种方案收益是a[i],一共选m次,每种方案最多连续选k次,要求选完m次后的最大值。
做法:排序,最大的连续选了k次后,选一次第二大,就这样以k个第一大+一个第二大作为循环节,m/(k+1)就是总共有多少个循环节,循环节的值=k*a[1] + a[2],再加上m%(k+1)*a[1]就是答案
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 200005;
ll a[maxn];
bool cmp(int a,int b)
{
return a > b;
}
int main()
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1; i<=n; i++)
{
cin>>a[i];
}
sort(a+1,a+1+n,cmp);
ll num,sum = 0;
num = m / (k+1);
sum = num * (a[1] * k + a[2]);
sum += (m%(k + 1)) * a[1];
cout<<sum;
}
http://codeforces.com/contest/1117/problem/C
题意:给你起点x1,y1,终点x2,y2,再给你n天的风向,你的船每天能朝东南西北任一方向走一格也可以不走,你的船每天走得路程=风向+你走的,问你最少多少天到达目的地,如果到达不了,输出-1。
做法:二分答案,二分范围为1-1e18,因为起点终点坐标的范围最大为1e9,先算出前i天风向一共走过的x,y,二分答案的时候check一下当前的天数是否大于等于终点的横坐标减这么多天风向改变的横坐标 + 纵坐标减这么多天风向改变的纵坐标,噢,而且是要绝对值。
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#include <vector>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 100005;
ll x[maxn],y[maxn];
char s[maxn];
int main()
{
ll x1,y1,x2,y2;
int n;
cin>>x1>>y1>>x2>>y2>>n;
cin>>s;
for(int i=1; i<=n; i++)
{
x[i] = x[i-1];
y[i] = y[i-1];
if(s[i-1] == 'U')
y[i]++;
if(s[i-1] == 'D')
y[i]--;
if(s[i-1] == 'L')
x[i]--;
if(s[i-1] == 'R')
x[i]++;
}
ll l = 1,r = 1e18,mid,ans = -1;
while(l < r)
{
mid = (l + r) / 2;
ll xx = x1 + mid / n * x[n] + x[mid%n];
ll yy = y1 + mid / n * y[n] + y[mid%n];
if(mid >= (abs(x2 - xx) + abs(y2 - yy)))
{
ans = mid;
r = mid;
}
else
{
l = mid + 1;
}
}
cout<<ans;
}