小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;
}