[LOJ2736] 「JOISC 2016 Day3」回轉壽司(分塊+堆)

題意

  • 給出一個有 NN 個點的環,環上各點有一個初始權值 aia_i,給出QQ個詢問,每次詢問給出一個區間 [l,r][l,r] 和一個值 AA ,對於 AA 的變動定義如下(rr 可能會小於 ll 因爲是環形)。
	for (int i = l; i <= r; i++) if(a[i] > A) swap(a[i], A);
  • 對於每個詢問,回答遍歷完區間 [l,r][l,r]AA 的最終值。

這個東西沒有什麼比較好的數據結構可以處理,那麼就考慮分塊,對於每個整塊一個數經過的時候只會改變它的最大值,那麼我們對於每個整塊用一個大根堆來維護其最大值,邊角塊的話我們可以暴力重構這個塊,區間內經過的值可以用一個小根堆來維護。

因爲新的值肯定來自原集合與經過的值,那麼每次把經過的值從小到大替換掉大於它的第一個即可,再把新的塊構建出來就可以了,這樣複雜度是O(nnlogn)O(n\sqrt{n}logn)

#include<bits/stdc++.h>
#include<bits/extc++.h>

#define file(s) freopen(s".in", "r", stdin), freopen(s".out", "w", stdout)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define For(i, a, b) for(register int i = (a), i##_end_ = (b); i <= i##_end_; ++ i)
#define FOR(i, a, b) for(register int i = (a), i##_end_ = (b); i >= i##_end_; -- i)
#define debug(x) cout << #x << " = " << x << endl
#define mem(a, b) memset(a, b, sizeof(a))
#define cpy(a, b) memcpy(a, b, sizeof(a))
#define inf (0x3f3f3f3f)
#define INF (1e18)
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define y1 orzorz

typedef unsigned long long ull;
typedef unsigned int uint;
typedef long long ll;
typedef std::pair<ll, int> PLI;
typedef std::pair<int, int> PII;
typedef long double ldb;
typedef double db;

namespace IO {
#define getc() ((S_ == T_) && (T_ = (S_ = Ch_) + fread(Ch_, 1, Buffsize, stdin), S_ == T_) ? 0 : *S_ ++)
#define putc(x) *nowps ++ = (x)

	const uint Buffsize = 1 << 15, Output = 1 << 23;
	static char Ch_[Buffsize], *S_ = Ch_, *T_ = Ch_;
	static char Out[Output], *nowps = Out;

	inline void flush() {fwrite(Out, 1, nowps - Out, stdout); nowps = Out;}
	template<class T>inline bool chkmax(T &_, T __) {return _ < __ ? _ = __, 1 : 0;}
	template<class T>inline bool chkmin(T &_, T __) {return _ > __ ? _ = __, 1 : 0;}

	template<class T>inline void read(T &_) {
		_ = 0; static char __; T ___ = 1;
		for(__ = getc(); !isdigit(__); __ = getc()) if(__ == '-') ___ = -1;
		for(; isdigit(__); __ = getc()) _ = (_ << 3) + (_ << 1) + (__ ^ 48);
		_ *= ___;
	}

	template<class T>inline void write(T _, char __ = '\n') {
		if(!_) putc('0');
		if(_ < 0) putc('-'), _ = -_;
		static uint sta[111], tp;
		for(tp = 0; _; _ /= 10) sta[++ tp] = _ % 10;
		for(; tp; putc(sta[tp --] ^ 48)); putc(__);
	}

	inline void procStatus() {
		std::ifstream t("/proc/self/status");
		std::cerr << std::string(std::istreambuf_iterator<char>(t), std::istreambuf_iterator<char>());
	}
}

using namespace std;
using namespace IO;

const int N = 4e5 + 10;
const int size = 500;

int st[N], ed[N], a[N], be[N], cnt, n, q;

priority_queue<int, vector<int>, greater<int> > Q[N];
priority_queue<int> h[N];

void clear(priority_queue<int, vector<int>, greater<int> > &ovo) {
	priority_queue<int, vector<int>, greater<int> > qaq; swap(qaq, ovo);
}

void Clear(priority_queue<int> &ovo) {
	priority_queue<int> qaq; swap(qaq, ovo);
}

void rebuild(int bh, int l, int r, int &v) {
	For(i, st[bh], ed[bh]) Q[bh].push(a[i]), a[i] = Q[bh].top(), Q[bh].pop();
	For(i, l, r) if(a[i] > v) swap(a[i], v);
	Clear(h[bh]), clear(Q[bh]);
	For(i, st[bh], ed[bh]) h[bh].push(a[i]);
}

void update(int l, int r, int &v) {
	int L = be[l], R = be[r];
	if(L ^ R) {
		rebuild(L, l, ed[L], v);
		For(i, L + 1, R - 1) {
			Q[i].push(v);
			int k = h[i].top(); h[i].pop();
			if(k > v) swap(k, v);
			h[i].push(k);
		}
		rebuild(R, st[R], r, v);
	}
	else rebuild(L, l, r, v);
}

int main() {
#ifdef ylsakioi
	file("in");
#endif

	int l, r, v;

	read(n), read(q);
	For(i, 1, n) {
		if(i % size == 1) st[++ cnt] = i;
		if(i % size == 0 || i == n) ed[cnt] = i;
		read(a[i]), be[i] = cnt, h[cnt].push(a[i]);
	}

	while(q --) {
		read(l), read(r), read(v);
		if(l <= r) update(l, r, v);
		else update(l, n, v), update(1, r, v);
		write(v);
	}

	return flush(), 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章