最后六个点超时超了50ms
查看原帖
最后六个点超时超了50ms
739515
wc3624762194楼主2024/10/25 21:36

有没有大佬帮忙优化一下,球球了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 7;
const ll inf = 1e18 + 7;
ll n, q, w;
ll num[N], times, now;
void read(ll & a) {
	ll s = 0, w = 1;
	char ch = getchar();
	while (ch < '0' || '9' < ch) {
		if (ch == '-')w = -1;
		ch = getchar();
	}
	while ('0' <= ch && ch <= '9') {
		s = s * 10 + ch - '0';
		ch = getchar();
	}
	a = s * w;
}
struct segment_tree
{
	struct node
	{
		int l, r;//开始位置,结束位置
		ll add, pre;
	}tr[N << 2];
	inline void pushup(int p)//条件修改
	{
		tr[p].pre = tr[p << 1].pre + tr[p << 1 | 1].pre;
	}
	inline void build(int p, int l, int r)
	{
		tr[p] = { l,r };
		if (l == r)
		{
			tr[p].pre = num[l];
			return;
		}
		int mid = (l + r) >> 1;
		build(p << 1, l, mid);
		build(p << 1 | 1, mid + 1, r);
		pushup(p);
	}
	inline void spread(int p)//懒标记
	{
		if (tr[p].add)
		{
			tr[p << 1].pre += (tr[p << 1].r - tr[p << 1].l + 1) * tr[p].add;
			tr[p << 1].add += tr[p].add;
			tr[p << 1 | 1].pre += (tr[p << 1 | 1].r - tr[p << 1 | 1].l + 1) * tr[p].add;
			tr[p << 1 | 1].add += tr[p].add;
			tr[p].add = 0;
		}
		return;
	}
	inline void modify(int p, int l, int r, ll k)//区间增加
	{
		if (tr[p].l >= l && tr[p].r <= r)
		{
			tr[p].pre += (tr[p].r - tr[p].l + 1) * k;
			tr[p].add += k;
			return;
		}
		spread(p);
		int mid = (tr[p].l + tr[p].r) >> 1;
		if (l <= mid) modify(p << 1, l, r, k);
		if (r > mid) modify(p << 1 | 1, l, r, k);
		pushup(p);
	}
	inline ll query(int p, int l, int r)//区间求和
	{
		ll ans = 0;
		if (tr[p].l >= l && tr[p].r <= r)
			return tr[p].pre;
		spread(p);
		int mid = (tr[p].l + tr[p].r) >> 1;
		if (l <= mid) ans += query(p << 1, l, r);
		if (r > mid) ans += query(p << 1 | 1, l, r);
		return ans;
	}
	inline int ask(int p, ll now)//线段树上直接进行二分
	{
		if (tr[p].l == tr[p].r) return tr[p].l;
		spread(p);
		if (tr[p << 1].pre * pow(2, times) >= now) return ask(p << 1, now);
		else return ask(p << 1 | 1, now - tr[p << 1].pre * pow(2, times));
	}
}ST;
int main()
{
	read(n), read(q), read(w);
	for (int i = 1; i <= n; ++i)
		read(num[i]);
	ST.build(1, 1, n);
	while (q--)
	{
		ll l, r, d;
		read(l), read(r), read(d);
		ST.modify(1, l, r, d);
		int ans = -1;
		now = w;//剩余多少血量
		ll kill = ST.query(1, 1, n);
		times = log(now / kill + 1) / log(2);//第几轮了
		kill *= (pow(2, times) - 1);
		now -= kill;
		ans += n * times;
		ans += ST.ask(1, now);//树上二分
		printf("%d\n", ans);
	}
	return 0;
}
2024/10/25 21:36
加载中...