A. Dual Trigger
当字符串中1的个数为奇数时显然为NO
另外当1的个数为2且这两个1的位置相邻是也是NO
其余情况都是YES
#include<bits/stdc++.h>
using namespace std;
int t , n;
char a;
string s;
int vis[500];
void solve() {
cin >> n;
cin >> s;
vector<int> v;int cnt = 0;
for (int i = 0;i < n;i++) {
if (s[i] == '1') cnt++;
}
for (int i = 0;i < n;i++) {
if (i + 1 < n && s[i] == '1' && s[i + 1] == '1' && cnt == 2) {
cout << "NO" << endl;
return;
}
}
for (int i = 0;i <= n;i++) vis[i] = 0;
if (cnt & 1) cout << "NO" << endl;
else cout << "YES" << endl;
}
int main() {
cin >> t;
while (t--) solve();
}
//111010101
B. Battle Cows
若数组中不存在比
a
[
k
]
a[k]
a[k]大的数,则答案为
n
−
1
n-1
n−1(把
a
[
k
]
a[k]
a[k]与
a
[
1
]
a[1]
a[1]交换即可)
反之,记数组中第一个比
a
[
k
]
a[k]
a[k]大的数的位置为pos
最优的交换方法有两种:
- 将 a [ k ] a[k] a[k]与 a [ 1 ] a[1] a[1]交换
- 将
a
[
k
]
a[k]
a[k]与
a
[
p
o
s
]
a[pos]
a[pos]交换
模拟这两种方法分别计算答案,取最大值即可
#include<bits/stdc++.h>
using namespace std;
int t , n , k , a[200005];
void solve() {
cin >> n >> k;
int ans1 , ans2 , ans3;
for (int i = 1;i <= n;i++) cin >> a[i];
int tmp = a[k];
int pos = -1;
for (int i = 1;i <= n;i++) {
if (a[i] > a[k]) {
pos = i;
break;
}
}
if (pos == -1) {
cout << n - 1 << endl;
return;
}
swap(a[pos] , a[k]);
int pos1 = -1;
for (int i = 1;i <= n;i++) {
if (a[i] > tmp) {
pos1 = i;
break;
}
}
swap(a[pos] , a[k]);
ans1 = pos1 - pos - (pos == 1 ? 1 : 0);
swap(a[k] , a[1]);
pos1 = -1;
for (int i = 1;i <= n;i++) {
if (a[i] > tmp) {
pos1 = i;
break;
}
}
ans2 = pos1 - 2;
//cout << ans1 << " " << ans2 << endl;
cout << max(ans1 , ans2) << endl;
}
int main() {
cin >> t;
while (t--) solve();
}
C. Ticket Hoarding
若在第i天买了x张票,则对答案的贡献为
x
∗
(
k
−
s
u
m
)
+
a
[
i
]
∗
x
x*(k-sum)+a\left[i\right]*x
x∗(k−sum)+a[i]∗x,这里sum指之前已经购买的票数(包括x)打表发现价格变化对答案的贡献与购买的顺序无关
证明:
设以下数列,其中
x
i
x_{i}
xi表示第i天购买的票数
x
1
.
.
.
.
x
i
.
.
.
.
x
j
.
.
.
.
x
n
x_{1}....x_{i}....x_{j}....x_{n}
x1....xi....xj....xn
其中
x
i
x_{i}
xi和
x
j
x_{j}
xj对答案的贡献总和为
x
i
∗
(
s
u
m
i
+
1
,
j
−
1
+
s
u
m
j
+
1
,
n
+
x
j
)
+
x
j
∗
s
u
m
j
+
1
,
n
+
x
j
∗
s
u
m
i
+
1
,
j
−
1
x_{i}*(sum_{i+1,j-1}+sum_{j+1,n}+x_{j})+x_{j}*sum_{j+1,n}+x_{j}*sum_{i+1,j-1}
xi∗(sumi+1,j−1+sumj+1,n+xj)+xj∗sumj+1,n+xj∗sumi+1,j−1接下来交换
x
i
x_{i}
xi和
x
j
x_{j}
xj它们的贡献变为
x
j
∗
(
s
u
m
i
+
1
,
j
−
1
+
s
u
m
j
+
1
,
n
+
x
i
)
+
x
i
∗
s
u
m
j
+
1
,
n
+
x
i
∗
s
u
m
i
+
1
,
j
−
1
x_{j}*(sum_{i+1,j-1}+sum_{j+1,n}+x_{i})+x_{i}*sum_{j+1,n}+x_{i}*sum_{i+1,j-1}
xj∗(sumi+1,j−1+sumj+1,n+xi)+xi∗sumj+1,n+xi∗sumi+1,j−1
二者相减为0
所以交换购买顺序不影响答案
然后显然选价格较少的贪心即可
//(ai+k-m)*xi
//dp[i]
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t , n , m , k;
struct node {
int val , pos , rnk;
}a[300005];
bool cmp1(node a , node b) { return a.val < b.val; }
bool cmp2(node a , node b) { return a.pos < b.pos; }
void solve() {
int ans = 0;
cin >> n >> m >> k;
for (int i = 1;i <= n;i++) cin >> a[i].val;
int cnt = 0;
sort(a + 1 , a + n + 1 , cmp1);
for (int i = 1;i <= n;i++) {
if (k >= m) {
ans += m * (a[i].val + cnt);
cnt += m;
k -= m;
}
else {
ans += k * (a[i].val + cnt);
cnt += k;
k = 0;
}
}
cout << ans << endl;
}
signed main() {
cin >> t;
while (t--) solve();
}
//a[i]*(k%m)