暴力的,O(NQ)可过的
大家好,我非常喜欢暴力数据结构,于是我就用分块过了这道题。
大家好,我非常喜欢暴力,于是我就没用数据结构过了这道题。
并且可能比大多数人的树套树和分块都块
跑到了峰值 800ms
在阅读之前你需要准备
- c++ 基础语法
- 或者使用 AI 平替
考虑本题每个操作的暴力算法:
- 查询
k 在区间内的排名:循环统计<k 的数的数量就行,O(\text{len}) 。 - 查询区间内排名为
k 的值:暴力nth_element时间复杂度O(\text{len}) ,可能会有较大常数。 - 修改某一位置上的数值:显然
O(1) 。 - 查询
k 在区间内的前驱:扫描整个区间,找到<k 的最大值即可,O(\text{len}) 。 - 查询
k 在区间内的后继:与4 操作同理,O(\text{len}) 。
总时间复杂度
提交发现 80pts TLE on #2 #9,对每个操作构造最坏情况发现最慢的操作是
回顾
上面算法已经严格 nth_element 状物(不用也能过)。
此时问题转变为维护
使用 vector 维护,因为 vector 对于 insert 操作和 erase 操作都有较优常数,那么
现在所有操作都是小常数
放一下我想到的,最应景的:WC2026 文艺汇演《暴力的,O(NQ)可过的》
全文没用用到任何普及组知识。
下面是平凡的代码:
#include <bits/stdc++.h>
using namespace std;
#ifdef __linux__
#define gc getchar_unlocked
#define pc putchar_unlocked
#else
#define gc getchar
#define pc putchar
#endif
//快读,不必要。
#define ds(x) (x=='\r'||x=='\n'||x==' ')
#define MAX 20
namespace fastIO {//吾常于「oi-wiki」习,自悟「快读快写」之术。
template<typename T>inline void r(T& a) { a = 0; char ch = gc(); bool ok = 0; for (; ch < '0' || ch>'9';)ok ^= (ch == '-'), ch = gc(); for (; ch >= '0' && ch <= '9';)a = (a << 1) + (a << 3) + (ch ^ 48), ch = gc(); if (ok)a = -a; }
template<typename T>inline void w(T a) { if (a == 0) { pc('0'); return; }static char ch[MAX]; int till = 0; if (a < 0) { pc('-'); for (; a;)ch[till++] = -(a % 10), a /= 10; } else for (; a;)ch[till++] = a % 10, a /= 10; for (; till;)pc(ch[--till] ^ 48); }
struct FIstream {
inline FIstream operator>>(int& a) { r(a); return{}; }
inline FIstream operator>>(char& ch) { ch = gc(); for (; ds(ch);)ch = gc(); return{}; }
inline FIstream operator>>(string& s) { s = ""; char ch = gc(); for (; ds(ch);)ch = gc(); for (; !(ds(ch) || ch == EOF);) { s.push_back(ch); ch = gc(); }return{}; }
template<typename T>inline FIstream operator<<(T& a) { r(a); return{}; }
inline void is(int n, string& s) { s = ""; char ch = gc(); for (; ds(ch);)ch = gc(); for (; n--;) { s.push_back(ch); ch = gc(); } }
}in;
struct FOstream {
inline FOstream operator<<(const int a) { w(a); return{}; }
inline FOstream operator<<(const char ch) { pc(ch); return{}; }
inline FOstream operator<<(const string s) { for (int i = 0; i < s.size(); i++)pc(s[i]); return{}; }
template<typename T>inline FOstream operator>>(const T a) { w(a); return{}; }
}out;
}using fastIO::in; using fastIO::out;
#undef ds
int a[50004];
int b[50004];
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
vector<pii>sorted;
map<pair<pii,int>,int>mp;
void Main() {
int n, m; in >> n >> m;
sorted.reserve(n+1);
for (int i = 1; i <= n; i++){
in >> a[i];
sorted.push_back({a[i],i});
}sort(all(sorted));
for (; m--;) {
int opt; in >> opt;
if (opt == 1) {
int l, r, k; in >> l >> r >> k;
int cnt = 1;
for (int i = l; i <= r; i++)cnt += (a[i] < k);
out << cnt << '\n';
}
else if (opt == 2) {
int l, r, k; in >> l >> r >> k;
pair<pii,int> x={{l,r},k};
if(mp.find(x)!=mp.end())//不必要
out<<mp[x]<<"\n";
else if(r-l<10000){//不必要
int len = r - l + 1;
memcpy(b, a + l, len * sizeof(int));
nth_element(b, b + k - 1, b + len);
out << (mp[x]=b[k - 1]) << '\n';
}else for(int i=0;i<n;i++){
k-=(sorted[i].second<=r&&sorted[i].second>=l);
if(!k){
out<<(mp[x]=sorted[i].first)<<'\n';
break;
}
}
}
else if (opt == 3) {
int pos, x; in >> pos >> x;
if(a[pos]==x)continue;
mp.clear();
int oldv=a[pos];
a[pos]=x;
auto it_old = lower_bound(all(sorted),make_pair(oldv,pos));
sorted.erase(it_old);
auto it_new = lower_bound(all(sorted),make_pair(x,pos));
sorted.insert(it_new, {x,pos});
}
else if (opt == 4) {
int ans = -2147483647;
int l, r, x; in >> l >> r >> x;
for (int i = l; i <= r; i++) {
if (a[i] < x)ans = max(ans, a[i]);
}
out << ans << '\n';
}
else {
int ans = 2147483647;
int l, r, x; in >> l >> r >> x;
for (int i = l; i <= r; i++) {
if (a[i] > x)ans = min(ans, a[i]);
}
out << ans << '\n';
}
}
}
signed main() {
Main();
return 0;
}