题意
- 给出一个有 N N N 个点的环,环上各点有一个初始权值 a i a_i ai,给出 Q Q Q个询问,每次询问给出一个区间 [ l , r ] [l,r] [l,r] 和一个值 A A A ,对于 A A A 的变动定义如下( r r r 可能会小于 l l l 因为是环形)。
for (int i = l; i <= r; i++) if(a[i] > A) swap(a[i], A);
- 对于每个询问,回答遍历完区间 [ l , r ] [l,r] [l,r] 后 A A A 的最终值。
这个东西没有什么比较好的数据结构可以处理,那么就考虑分块,对于每个整块一个数经过的时候只会改变它的最大值,那么我们对于每个整块用一个大根堆来维护其最大值,边角块的话我们可以暴力重构这个块,区间内经过的值可以用一个小根堆来维护。
因为新的值肯定来自原集合与经过的值,那么每次把经过的值从小到大替换掉大于它的第一个即可,再把新的块构建出来就可以了,这样复杂度是 O ( n n l o g n ) O(n\sqrt{n}logn) O(nnlogn)。
#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;
}