Luogu P4511 CTSC 2015 日程管理

正題

一開始的時候顯然第\(i\)天之前能夠放\(i\)個任務是吧,而後考慮用一棵線段樹維護這個數量,設天天的這個值爲\(lev(i)\)
考慮在\(t\)這個截止時間位置放了一個任務,那\((t,n)\)這個區間的$ lev(i)$ 都要減去\(1\)。   ui

插入

設插入的終止時間爲\(t\),這個任務的價值爲\(p\)。那如何插入呢?spa

  • 當這個任務與其餘的任務不衝突的時候,直接加入完事。也就是當\(min(lev(t\rightarrow n))>0\)的時候不會衝突,而後直接加進去就完事了
  • 當這個任務與其餘任務衝突的時候,一個顯然的想法就是替換掉最小的,或者不替換。那這個最小的值在哪裏找呢。爲了咱們能夠把當前的任務加進去,那原來的這個最小值的\(t_2\)必需要比剛剛所說的\((t,n)\)的最左邊的\(lev(i)=0\)\(i\)要小才能夠釋放空間讓當前的任務能夠插入。因此就在區間 \((1,id)\) (\(id\)就是剛剛說的那個位置)找一個價值最小的任務替換掉,而後把替換掉的那個任務丟到沒有用的一個集合。爲何是對的呢,由於若是不替換這個任務,那就要有一個更好的任務來替換這個任務,而這個任務比原來的要大,因此就要在中間額外插入一個任務,而顯然這是作不到的,因此這個就是最優的了。  

刪除

  • 顯然要是沒用這個任務直接刪掉完事
  • 其實這裏你不用管就有\(20\)分了,豈不美哉? 若是用了的話,就在沒有用的裏面去找個最大的替換要刪掉的那個任務就好了。萬一找不到的話就不用管了唄。 而後剩下的本身YY一下就出來了 我這麼弱都YY出來了您們確定隨便就搞出來了

至於這個集合怎麼維護,顯然線段樹套個multiset就好了code

代碼

至於代碼爲何這麼長
固然是爲了更好地裝逼說明啦!  
記得點贊啊,我就沒收過贊。。。  
下次必定的走開(bushiget

#include <set>
#include <cstdio>
#include <utility>
#include <algorithm>

using namespace std;

#define R register
#define LL long long
#define IT multiset<int>::iterator

const int MAXN = 3e5 + 10;
const int inf = 1e9 + 10;

inline int read()
{
	char a = getchar();
	int x = 0, f = 1;
	for (; a > '9' || a < '0'; a = getchar())
		if (a == '-')
			f = -1;
	for (; a >= '0' && a <= '9'; a = getchar())
		x = x * 10 + a - '0';
	return x * f;
}

inline char getc()
{
	char a = getchar();
	while (a != 'A' && a != 'D')
		a = getchar();
	return a;
}

int n, m;
LL Ans;

struct Round
{
	int l, r, va;
};

class Tree_for_value
{
private:
	int tag[MAXN << 2];
	Round mn[MAXN << 2];
	inline int ls(int x);
	inline int rs(int x);
	inline void update(int x);
	inline void get(int x, int k);
	inline void pushdown(int x);

public:
	inline Round ask(int x, int l, int r, int Le, int Ri);
	inline void chg(int x, int l, int r, int Le, int Ri, int k);
	inline void build(int x, int l, int r);
} T1;

class Tree_for_mintask
{
private:
	multiset<int> st[MAXN << 2];
	pair<int, int> mn[MAXN << 2];
	inline int ls(int x);
	inline int rs(int x);
	inline void update(int x);

public:
	inline void build(int x, int l, int r);
	inline void insert(int x, int l, int r, int ad, int p);
	inline void del(int x, int l, int r, int ad, int p);
	inline pair<int, int> ask(int x, int l, int r, int Le, int Ri);
	inline int have(int x, int l, int r, int ad, int p);
} T2;

class Tree_for_maxtask
{
private:
	multiset<int> st[MAXN << 2];
	pair<int, int> mx[MAXN << 2];
	inline int ls(int x);
	inline int rs(int x);
	inline void update(int x);

public:
	inline void build(int x, int l, int r);
	inline void insert(int x, int l, int r, int ad, int p);
	inline void del(int x, int l, int r, int ad, int p);
	inline pair<int, int> ask(int x, int l, int r, int Le, int Ri);
} T3;

int main()
{
	freopen("d.in", "r", stdin);
	freopen("d.out", "w", stdout);
	n = read();
	m = read();
	T1.build(1, 1, n);
	T2.build(1, 1, n);
	T3.build(1, 1, n);
	char op;
	int t, p;
	while (m--)
	{
		op = getc();
		t = read();
		p = read();
		if (op == 'A')
		{
			Round pir = T1.ask(1, 1, n, t, n);
			if (pir.va > 0)
			{
				Ans += p;
				T1.chg(1, 1, n, t, n, -1);
				T2.insert(1, 1, n, t, p);
			}
			else
			{
				int id = pir.l;
				pair<int, int> tmp = T2.ask(1, 1, n, 1, id);
				if (tmp.first > p)
					T3.insert(1, 1, n, t, p);
				else
				{
					Ans += p - tmp.first;
					T2.del(1, 1, n, tmp.second, tmp.first);
					T3.insert(1, 1, n, tmp.second, tmp.first);
					T1.chg(1, 1, n, tmp.second, n, 1);
					T2.insert(1, 1, n, t, p);
					T1.chg(1, 1, n, t, n, -1);
				}
			}
		}
		else
		{
			if (T2.have(1, 1, n, t, p) == 0)
				T3.del(1, 1, n, t, p);
			else
			{
				Ans -= p;
				T2.del(1, 1, n, t, p);
				T1.chg(1, 1, n, t, n, 1);
				Round tmp = T1.ask(1, 1, n, 1, n);
				int id = tmp.va <= 0 ? tmp.r : 0;
				if (id != n)
				{
					pair<int, int> tmp = T3.ask(1, 1, n, id + 1, n);
					if (tmp.first != -inf)
					{
						T3.del(1, 1, n, tmp.second, tmp.first);
						T2.insert(1, 1, n, tmp.second, tmp.first);
						T1.chg(1, 1, n, tmp.second, n, -1);
						Ans += tmp.first;
					}
				}
			}
		}
		printf("%lld\n", Ans);
	}
	return 0;
}

inline int Tree_for_value::ls(int x) { return x << 1; }
inline int Tree_for_value::rs(int x) { return x << 1 | 1; }
inline void Tree_for_value::update(int x)
{
	if (mn[ls(x)].va == mn[rs(x)].va)
	{
		mn[x].va = mn[ls(x)].va;
		mn[x].l = mn[ls(x)].l;
		mn[x].r = mn[rs(x)].r;
	}
	if (mn[ls(x)].va < mn[rs(x)].va)
		mn[x] = mn[ls(x)];
	if (mn[ls(x)].va > mn[rs(x)].va)
		mn[x] = mn[rs(x)];
}
inline void Tree_for_value::get(int x, int k)
{
	tag[x] += k;
	mn[x].va += k;
}
inline void Tree_for_value::pushdown(int x)
{
	if (tag[x])
	{
		get(ls(x), tag[x]);
		get(rs(x), tag[x]);
		tag[x] = 0;
	}
}
inline void Tree_for_value::build(int x, int l, int r)
{
	if (l == r)
	{
		mn[x] = {l, l, l};
		return;
	}
	int mid = l + r;
	mid >>= 1;
	build(ls(x), l, mid);
	build(rs(x), mid + 1, r);
	update(x);
}
inline void Tree_for_value::chg(int x, int l, int r, int Le, int Ri, int k)
{
	if (l >= Le && r <= Ri)
	{
		get(x, k);
		return;
	}
	pushdown(x);
	int mid = l + r;
	mid >>= 1;
	if (Le <= mid)
		chg(ls(x), l, mid, Le, Ri, k);
	if (Ri > mid)
		chg(rs(x), mid + 1, r, Le, Ri, k);
	update(x);
}
inline Round Tree_for_value::ask(int x, int l, int r, int Le, int Ri)
{
	if (l >= Le && r <= Ri)
		return mn[x];
	pushdown(x);
	int mid = l + r;
	mid >>= 1;
	Round ans;
	if (Le > mid)
		ans = ask(rs(x), mid + 1, r, Le, Ri);
	else if (Ri <= mid)
		return ans = ask(ls(x), l, mid, Le, Ri);
	else
	{
		Round lef = ask(ls(x), l, mid, Le, Ri), rig = ask(rs(x), mid + 1, r, Le, Ri);
		if (lef.va < rig.va)
			ans = lef;
		if (lef.va > rig.va)
			ans = rig;
		if (lef.va == rig.va)
		{
			ans.l = lef.l;
			ans.r = rig.r;
			ans.va = lef.va;
		}
	}
	update(x);
	return ans;
}

inline int Tree_for_mintask::ls(int x) { return x << 1; }
inline int Tree_for_mintask::rs(int x) { return x << 1 | 1; }
inline void Tree_for_mintask::update(int x)
{
	if (mn[ls(x)].first <= mn[rs(x)].first)
		mn[x] = mn[ls(x)];
	else
		mn[x] = mn[rs(x)];
}
inline void Tree_for_mintask::build(int x, int l, int r)
{
	if (l == r)
	{
		mn[x] = make_pair(inf, l);
		return;
	}
	int mid = l + r;
	mid >>= 1;
	build(ls(x), l, mid);
	build(rs(x), mid + 1, r);
	update(x);
}
inline void Tree_for_mintask::insert(int x, int l, int r, int ad, int p)
{
	if (l == r)
	{
		st[x].insert(p);
		mn[x].first = min(mn[x].first, p);
		return;
	}
	int mid = l + r;
	mid >>= 1;
	if (ad <= mid)
		insert(ls(x), l, mid, ad, p);
	else
		insert(rs(x), mid + 1, r, ad, p);
	update(x);
}
inline void Tree_for_mintask::del(int x, int l, int r, int ad, int p)
{
	if (l == r)
	{
		st[x].erase(st[x].find(p));
		if (st[x].size())
			mn[x].first = *st[x].begin();
		else
			mn[x].first = inf;
		return;
	}
	int mid = l + r;
	mid >>= 1;
	if (ad <= mid)
		del(ls(x), l, mid, ad, p);
	if (ad > mid)
		del(rs(x), mid + 1, r, ad, p);
	update(x);
}
inline pair<int, int> Tree_for_mintask::ask(int x, int l, int r, int Le, int Ri)
{
	if (l >= Le && r <= Ri)
		return mn[x];
	int mid = l + r;
	mid >>= 1;
	if (Le > mid)
		return ask(rs(x), mid + 1, r, Le, Ri);
	if (Ri <= mid)
		return ask(ls(x), l, mid, Le, Ri);
	pair<int, int> lef = ask(ls(x), l, mid, Le, Ri), rig = ask(rs(x), mid + 1, r, Le, Ri);
	if (lef.first <= rig.first)
		return lef;
	return rig;
}
inline int Tree_for_mintask::have(int x, int l, int r, int ad, int p)
{
	if (l == r)
		return st[x].find(p) != st[x].end();
	int mid = l + r;
	mid >>= 1;
	if (ad <= mid)
		return have(ls(x), l, mid, ad, p);
	else
		return have(rs(x), mid + 1, r, ad, p);
}

inline int Tree_for_maxtask::ls(int x) { return x << 1; }
inline int Tree_for_maxtask::rs(int x) { return x << 1 | 1; }
inline void Tree_for_maxtask::update(int x)
{
	if (mx[ls(x)].first > mx[rs(x)].first)
		mx[x] = mx[ls(x)];
	else
		mx[x] = mx[rs(x)];
}
inline void Tree_for_maxtask::build(int x, int l, int r)
{
	if (l == r)
	{
		mx[x] = make_pair(-inf, l);
		return;
	}
	int mid = l + r;
	mid >>= 1;
	build(ls(x), l, mid);
	build(rs(x), mid + 1, r);
	update(x);
}
inline void Tree_for_maxtask::insert(int x, int l, int r, int ad, int p)
{
	if (l == r)
	{
		st[x].insert(p);
		mx[x].first = max(mx[x].first, p);
		return;
	}
	int mid = l + r;
	mid >>= 1;
	if (ad <= mid)
		insert(ls(x), l, mid, ad, p);
	else
		insert(rs(x), mid + 1, r, ad, p);
	update(x);
}
inline void Tree_for_maxtask::del(int x, int l, int r, int ad, int p)
{
	if (l == r)
	{
		st[x].erase(st[x].find(p));
		if (st[x].size())
		{
			IT it = st[x].end();
			it--;
			mx[x].first = *it;
		}
		else
			mx[x].first = -inf;
		return;
	}
	int mid = l + r;
	mid >>= 1;
	if (ad <= mid)
		del(ls(x), l, mid, ad, p);
	if (ad > mid)
		del(rs(x), mid + 1, r, ad, p);
	update(x);
}
inline pair<int, int> Tree_for_maxtask::ask(int x, int l, int r, int Le, int Ri)
{
	if (l >= Le && r <= Ri)
		return mx[x];
	int mid = l + r;
	mid >>= 1;
	if (Le > mid)
		return ask(rs(x), mid + 1, r, Le, Ri);
	if (Ri <= mid)
		return ask(ls(x), l, mid, Le, Ri);
	pair<int, int> lef = ask(ls(x), l, mid, Le, Ri), rig = ask(rs(x), mid + 1, r, Le, Ri);
	if (lef.first > rig.first)
		return lef;
	return rig;
}
相關文章
相關標籤/搜索