第一题
条件等价于最终的结果中必须存在子串 RL ,所以只要原字符串中存在 LR 或 RL 则本题有解,若先搜索到 LR 则输出其中 L 的下标+1 的值,若先搜索到 RL 则输出 0,若字符串中只有 L 或 R 则输出 −1 。
第二题
题意:给定一个数组长度 n ,求是否存在满足数组中各元素之和等于任意两相邻元素之和的数组,若存在则举例
注:2≤n≤1000
若 n 为偶数,则必可构造出该数组:[1,−1,1,−1,...]
若 n 为奇数,则分两种情况:
- 若 n=3 ,则无解
- 若 n 为其他任意奇数,则必可构造出数组:[−(n/2−1),n/2,−(n/2−1),n/2,...]
第三题
题意:给定长度为 n 的数组 a ,给定 m ,有一操作可使数组 a 中某一元素取负,即 ai=−ai ,求使 a[1]+a[2]+...+a[m] 为最小前缀和的操作数
即对于给定的 m(1≤m≤n) ,都有任何一个 k(1≤k≤m) ,使 a[1]+a[2]+a[3]+...+a[k]≥a[1]+a[2]+a[3]+...+a[m]
我们定义 [L,R]=a[L]+a[L+1]+...+a[R−1]+a[R]
分类讨论一下:
- k≤m 时,
- a[1,k]≥a[1,m]⇒a[1,k]+a[k+1,m]>=a[1,m]⇒a[k+1,m]≤0
- 可以得到,任意的 i∈[2,m] 都有 a[i,m]≤0
- k>m 时,
- a[1,k]≥a[1,m]⇒a[1,m]+a[m+1,k]≥a[1,m]⇒a[m+1,k]≥0
- 可以得到,任意的 i∈[m+1,n] 都有 a[m+1,i]≥0
所以我们贪心的考虑即可
代码:
LL T;
cin >> T;
while (T --)
{
LL n, m;
cin >> n >> m;
multiset<LL> st;
for (int i = 1;i <= n;i ++) cin >> a[i];
LL sum = 0, res = 0;
for (int i = m;i >= 2;i --) // 倒序
{
sum += a[i];
st.insert(a[i]);
while (sum > 0) // 贪心的把最大的数取负
{
LL t = *(prev(st.end()));
sum -= t;
sum += -1 * t;
st.erase(prev(st.end()));
res ++;
}
}
st.clear();
sum = 0;
for (int i = m + 1;i <= n;i ++)
{
sum += a[i];
st.insert(a[i]);
while (sum < 0) // 贪心的把最小的数取负
{
LL t = *(st.begin());
sum -= t;
sum += -1 * t;
st.erase(st.begin());
res ++;
}
}
cout << res << endl;
}
第四题(未解决)
贪心+数据结构
补题网址:https://zhuanlan.zhihu.com/p/596398202