[賽記] csp-s加賽1

Peppa_Even_Pig發表於2024-09-18

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

相關文章