题一:A Good Game
题解:利用前缀和,求出所有区间值,然后操作排序,贪心求解即可
知识点:前缀和 + 贪心
AC代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<map>
#include<string.h>
#include<string>
using namespace std;
const int N = 1e6 + 15;
#define ll long long
#define inf 0x3f3f3f3f
ll a[N], sum[N];
ll b[N];
int main()
{
int t; cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> a[i];
sum[0] = a[0];
for (int i = 1; i < n; i++)
sum[i] = sum[i - 1] + a[i];
int k = 0;
for (int i = 0; i < m; i++) {
int l, r;
cin >> l >> r;
int x = sum[r - 1] - sum[l - 2];
b[k++] = x;
}
sort(b, b + k);
ll res = 0;
for (int i = 1; i <= k; i++)
res += i * b[i - 1];
cout << res << endl;
}
return 0;
}
题二:Prefix
题解:map瞎搞,记录前缀的数量,暴力就可以过,对于我这种只会做签到题的菜鸡。不过这题更好的解法是字典树。
注意:记得把所有的有关数据都开ll,以免相乘的时候出现精度丢失
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<map>
#include<string.h>
#include<string>
using namespace std;
const int N = 5e5 + 15;
#define ll long long
#define inf 0x3f3f3f3f
ll val[N];
string str[N];
map<string, ll>mp;
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n, m; cin >> n >> m;
ll s_val[30];
for (int i = 0; i < 26; i++)
cin >> s_val[i];
for (int i = 0; i < n; i++) {
cin >> str[i];
int str_len = str[i].length();
string s;
val[i] = 1;
for (int j = 0; j < str_len; j++) {
s += str[i][j];
mp[s] += 1;
val[i] = (val[i] * s_val[str[i][j] - 'a']) % m;
}
}
for (int i = 0; i < n; i++) {
string s;
int v = 1;
int ans = 0;
for (int j = 0; j < str[i].length(); j++) {
v = (v * s_val[str[i][j] - 'a']) % m;
s += str[i][j];
if (v > val[i])
ans += mp[s];
}
cout << ans << " ";
}
cout << endl;
return 0;
}
题三:Sequence
题解:线段树的更新,改点,异或的应用
AC代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<map>
#include<string.h>
#include<string>
using namespace std;
const int N = 2e5 + 15;
#define ll long long
#define inf 0x3f3f3f3f
struct Tree {
int l, r;
int val,sum;
}tree[N * 2];
int a[N];
void pushup(int cur) {
if ((tree[cur * 2 + 1].l - tree[cur].l) % 2 == 0)
tree[cur].val = tree[cur * 2].val ^ tree[cur * 2 + 1].val;
else
tree[cur].val = tree[cur * 2].val ^ (tree[cur * 2 + 1].sum ^ tree[cur * 2 + 1].val);
tree[cur].sum = tree[cur * 2].sum ^ tree[cur * 2 + 1].sum;
}
void build(int l, int r, int step) {
int mid = (l + r) / 2;
tree[step].l = l, tree[step].r = r;
if (l == r) {
tree[step].val = a[l];
tree[step].sum = a[l];
return;
}
build(l, mid, step * 2);
build(mid + 1, r, step * 2 + 1);
pushup(step);
}
void query(int l, int r, int &x, int &y, int step) {
if (tree[step].l == l && tree[step].r == r) {
x = tree[step].val, y = tree[step].sum;
return;
}
int mid = (tree[step].l + tree[step].r) / 2;
if (r <= mid)
query(l, r, x, y, step * 2);
else if (l > mid)
query(l, r, x, y, step * 2 + 1);
else {
int a, b, c, d;
query(l, mid, a, b, step * 2);
query(mid + 1, r, c, d, step * 2 + 1);
if ((tree[step * 2 + 1].l - l) % 2 == 0) {
x = a ^ c;
y = b ^ d;
}
else {
x = a ^ (d ^ c);
y = b ^ d;
}
}
}
void update(int tar, int val, int step) {
int l = tree[step].l, r = tree[step].r;
if (l == r) {
tree[step].val = val;
tree[step].sum = val;
return;
}
int mid = (l + r) / 2;
if (tar <= mid)
update(tar, val, step * 2);
else
update(tar, val, step * 2 + 1);
pushup(step);
}
int main()
{
int t;
scanf("%d", &t);
int k = 1;
while (t--) {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, n, 1);
printf("Case #%d:\n", k++);
for (int i = 0; i < m; i++) {
int op, x, y;
scanf("%d%d%d", &op, &x, &y);
if (op == 0)
update(x, y, 1);
else {
if ((y - x + 1) % 2 != 0) {
int a, b;
query(x, y, a, b, 1);
printf("%d\n", a);
}
else
printf("0\n");
}
}
}
return 0;
}