小W与制胡串谜题 50pts
这种题,就是想到 + 玄学;
感觉刚接触OI时做过这种题,当时学得少,蒙一下就过了。现在蒙不了了,也确实可供想的方向很多,所以像这种签到题比较不好做;
字符串数组是可以 $ sort $ 的,所以我们重载 $ cmp $ 为 a + b < b + a
即可;
至于正确性,直观感觉一下确实是对的,要严谨证明一下的话需要证一下偏序关系。
点击查看代码
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
int n;
string s[300005];
bool cmp(string a, string b) {
return a + b < b + a;
}
int main() {
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> s[i];
}
sort(s + 1, s + 1 + n, cmp);
for (int i = 1; i <= n; i++) {
cout << s[i];
}
return 0;
}
小W与伙伴招募 85pts
这题数据比较NB,赛时我打的假贪心拿了85pts,但暴力能拿95pts(貌似和正解得分没啥区别)。。。
很显然的一个思路是贪心,每次顺序优先购买花费最少的钻石;
这样我们就得到了一个 $ \Theta(nm) $ 的暴力;
考虑优化,我们发现,每次操作相当于一个区间乘2(在原数组基础上)和单点减的问题,所以我们把每个点看成一个类似于 $ xb_i + b $ 的形式,然后开两个线段树维护一下 $ x $ 和 $ b $ 即可;
由于每次操作需要在线段树上二分,所以时间复杂度是 $ \Theta(n \log^2 m) $ 的 (貌似可以 $ \Theta(n \log m) $ 实现);
点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define int long long
int n, m;
long long c[500005];
long long sum[500005], suma[500005];
int len, pos;
long long ans;
struct sss{
long long a, b;
bool operator <(const sss &A) const {
if (a != A.a) return a < A.a;
else return b < A.b;
}
}e[500005];
int cnt;
inline int ls(int x) {
return x << 1;
}
inline int rs(int x) {
return x << 1 | 1;
}
namespace xseg{
struct sss{
int l, r;
long long sum, lz, val;
bool z;
}tr[2000005];
inline void push_down(int id) {
if (tr[id].z) {
tr[ls(id)].z = tr[rs(id)].z = true;
tr[ls(id)].sum = tr[rs(id)].sum = tr[ls(id)].val = tr[rs(id)].val = 0;
tr[ls(id)].lz = tr[rs(id)].lz = -1;
tr[id].z = false;
}
if (tr[id].lz != -1) {
tr[ls(id)].lz += ((tr[ls(id)].lz == -1) ? (tr[id].lz + 1) : tr[id].lz);
tr[rs(id)].lz += ((tr[rs(id)].lz == -1) ? (tr[id].lz + 1) : tr[id].lz);
tr[ls(id)].sum += tr[id].lz * (sum[tr[ls(id)].r] - sum[tr[ls(id)].l - 1]);
tr[rs(id)].sum += tr[id].lz * (sum[tr[rs(id)].r] - sum[tr[rs(id)].l - 1]);
tr[ls(id)].val += tr[id].lz * (suma[tr[ls(id)].r] - suma[tr[ls(id)].l - 1]);
tr[rs(id)].val += tr[id].lz * (suma[tr[rs(id)].r] - suma[tr[rs(id)].l - 1]);
tr[id].lz = -1;
}
}
inline void push_up(int id) {
tr[id].sum = tr[ls(id)].sum + tr[rs(id)].sum;
tr[id].val = tr[ls(id)].val + tr[rs(id)].val;
}
void bt(int id, int l, int r) {
tr[id].l = l;
tr[id].r = r;
tr[id].lz = -1;
tr[id].z = false;
if (l == r) return;
int mid = (l + r) >> 1;
bt(ls(id), l, mid);
bt(rs(id), mid + 1, r);
}
void add(int id, int l, int r, long long d) {
if (tr[id].l >= l && tr[id].r <= r) {
if (d == 0) {
tr[id].lz = -1;
tr[id].sum = 0;
tr[id].val = 0;
tr[id].z = true;
return;
}
tr[id].sum += (sum[tr[id].r] - sum[tr[id].l - 1]) * d;
tr[id].val += (suma[tr[id].r] - suma[tr[id].l - 1]) * d;
tr[id].lz += ((tr[id].lz == -1) ? (d + 1) : d);
return;
}
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if (l <= mid) add(ls(id), l, r, d);
if (r > mid) add(rs(id), l, r, d);
push_up(id);
}
long long ask_sum(int id, int l, int r) {
if (tr[id].l >= l && tr[id].r <= r) return tr[id].sum;
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if (r <= mid) return ask_sum(ls(id), l, r);
else if (l > mid) return ask_sum(rs(id), l, r);
else return ask_sum(ls(id), l, mid) + ask_sum(rs(id), mid + 1, r);
}
long long ask_val(int id, int l, int r) {
if (tr[id].l >= l && tr[id].r <= r) return tr[id].val;
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if (r <= mid) return ask_val(ls(id), l, r);
else if (l > mid) return ask_val(rs(id), l, r);
else return ask_val(ls(id), l, mid) + ask_val(rs(id), mid + 1, r);
}
}
namespace bseg{
struct sss{
int l, r;
long long sum, val, lz;
}tr[2000005];
void bt(int id, int l, int r) {
tr[id].l = l;
tr[id].r = r;
tr[id].lz = -1;
if (l == r) return;
int mid = (l + r) >> 1;
bt(ls(id), l, mid);
bt(rs(id), mid + 1, r);
}
inline void push_up(int id) {
tr[id].sum = tr[ls(id)].sum + tr[rs(id)].sum;
tr[id].val = tr[ls(id)].val + tr[rs(id)].val;
}
inline void push_down(int id) {
if (tr[id].lz == 0) {
tr[ls(id)].lz = tr[rs(id)].lz = tr[ls(id)].sum = tr[rs(id)].sum = tr[ls(id)].val = tr[rs(id)].val = 0;
tr[id].lz = -1;
return;
}
}
void add(int id, int l, int r, long long d, bool is) {
if (tr[id].l >= l && tr[id].r <= r) {
if (is) {
tr[id].sum += d;
tr[id].val += d * e[l].a;
return;
}
tr[id].lz = 0;
tr[id].sum = 0;
tr[id].val = 0;
return;
}
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if (l <= mid) add(ls(id), l, r, d, is);
if (r > mid) add(rs(id), l, r, d, is);
push_up(id);
}
long long ask_sum(int id, int l, int r) {
if (tr[id].l >= l && tr[id].r <= r) return tr[id].sum;
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if (r <= mid) return ask_sum(ls(id), l, r);
else if (l > mid) return ask_sum(rs(id), l, r);
else return ask_sum(ls(id), l, mid) + ask_sum(rs(id), mid + 1, r);
}
long long ask_val(int id, int l, int r) {
if (tr[id].l >= l && tr[id].r <= r) return tr[id].val;
push_down(id);
int mid = (tr[id].l + tr[id].r) >> 1;
if (r <= mid) return ask_val(ls(id), l, r);
else if (l > mid) return ask_val(rs(id), l, r);
else return ask_val(ls(id), l, mid) + ask_val(rs(id), mid + 1, r);
}
}
bool ck(int x, long long o) {
long long s = xseg::ask_sum(1, 1, x) + bseg::ask_sum(1, 1, x);
if (s > o) return true;
else return false;
}
main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
long long a, b;
for (int i = 1; i <= m; i++) {
cin >> a >> b;
if (b != 0) {
e[++cnt].a = a;
e[cnt].b = b;
}
}
sort(e + 1, e + 1 + cnt);
for (int i = 1; i <= cnt; i++) {
if (e[i].b == -1) {
pos = i;
break;
}
sum[i] = sum[i - 1] + e[i].b;
suma[i] = suma[i - 1] + e[i].a * e[i].b;
}
if (pos != 1) xseg::bt(1, 1, pos - 1);
if (pos != 1) bseg::bt(1, 1, pos - 1);
for (int i = 1; i <= n; i++) {
if (pos != 1) xseg::add(1, 1, pos - 1, 1);
int l = 1;
int r = pos - 1;
int now = pos;
if (pos != 1) {
while(l <= r) {
int mid = (l + r) >> 1;
if (ck(mid, c[i])) {
now = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
}
long long s = 0;
now--;
if (now >= 1) {
s = xseg::ask_sum(1, 1, now) + bseg::ask_sum(1, 1, now);
ans += xseg::ask_val(1, 1, now) + bseg::ask_val(1, 1, now);
xseg::add(1, 1, now, 0);
bseg::add(1, 1, now, 0, 0);
}
if (s == c[i]) continue;
c[i] -= s;
now++;
if (now == pos) {
ans += e[pos].a * c[i];
continue;
}
ans += e[now].a * c[i];
bseg::add(1, now, now, -c[i], 1);
}
cout << ans;
return 0;
}