#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<map>
#include<string>
#include<vector>
#include<set>
#include<bitset>
#include<algorithm>
#include<ctime>
using namespace std;
#define ll long long
#define lb long double
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define endl '\n'
#define clr(a, b) memset(a, b, sizeof(a))
#define lowbit(x) x & -x
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define PB push_back
#define POP pop_back
#define max_ll 9223372036854775807
#define PII pair<int, int>
#define random(x) (rand()%x)
//srand((ll)time(0));
//freopen("E://one.txt","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("E://oneout.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
//std::ios::sync_with_stdio(false);
const double eps = 1e-14;
const double pi = acos(-1);
const int maxn = 5e4 + 10;//30000000
const int maxm = maxn * 21;
const ll mod = 1e9 + 7;
const int hash_mod = 19260817;
const int inf = 2147483647;
int n, m, sz;
int tree[maxm], siz[maxm], val[maxm], ls[maxm], rs[maxm], a[maxn];
ll key[maxm];
inline int read(){
char ch = getchar();
int x = 0, f = 1;
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while('0' <= ch && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
inline void write(int x){
if (x < 0) x = ~x + 1, putchar('-');
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
inline int add(int k){
siz[++sz] = 1;
val[sz] = k;
key[sz] = rand();
return sz;
}
inline void pushup(int rt){siz[rt] = siz[ls[rt]] + siz[rs[rt]] + 1;}
inline void split(int rt, int k, int & x, int & y){
if(!rt){
x = y = 0;
return;
}
if(val[rt] <= k){
x = rt;
split(rs[rt], k, rs[rt], y);
}
else{
y = rt;
split(ls[rt], k, x, ls[rt]);
}
pushup(rt);
}
inline int hebin(int x, int y){
if(!x || !y) return x + y;
if(key[x] < key[y]){
rs[x] = hebin(rs[x], y);
pushup(x);
return x;
}
else{
ls[y] = hebin(x, ls[y]);
pushup(y);
return y;
}
}
inline void Insert(int & rt, int k){
int x, y;
split(rt, k, x, y);
rt = hebin(hebin(x, add(k)), y);
}
inline void Delete(int & rt, int k){
int x, y, z;
split(rt, k, x, z);
split(x, k-1, x, y);
y = hebin(ls[y], rs[y]);
rt = hebin(hebin(x, y), z);
}
inline void build(int rt, int l, int r){
for(int i = l ; i <= r ; ++ i) Insert(tree[rt], a[i]);
if(l == r) return;
int mid = (l + r) >> 1;
build(lson); build(rson);
}
inline int Krank(int & rt, int k){
int x, y;
split(rt, k - 1, x, y);
int rk = siz[x];
rt = hebin(x, y);
return rk;
}
inline int Kth(int rt, int k){
while(1){
if(k <= siz[ls[rt]]) rt = ls[rt];
else if(k == siz[ls[rt]] + 1) return rt;
else {k -= (siz[ls[rt]] + 1); rt = rs[rt];}
}
}
inline int lst(int & rt, int k){
int x, y, num;
split(rt, k - 1, x, y);
if(siz[x]) num = val[Kth(x, siz[x])];
else num = -inf;
rt = hebin(x, y);
return num;
}
inline int nxt(int & rt, int k){
int x, y, num;
split(rt, k, x, y);
if(siz[y]) num = val[Kth(y, 1)];
else num = inf;
rt = hebin(x, y);
return num;
}
inline int q1(int rt, int l, int r, int L, int R, int k){
if(L <= l && r <= R) return Krank(tree[rt], k);
int mid = (l + r) >> 1;
int ans = 0;
if(L <= mid) ans += q1(lson, L, R, k);
if(R > mid) ans += q1(rson, L, R, k);
return ans;
}
inline void q3(int rt, int l, int r, int pos, int k){
Delete(tree[rt], a[pos]);
Insert(tree[rt], k);
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid) q3(lson, pos, k);
if(pos > mid) q3(rson, pos, k);
}
inline int q4(int rt, int l, int r, int L, int R, int k){
if(L <= l && r <= R) return lst(tree[rt], k);
int mid = (l + r) >> 1;
int ans = -inf;
if(L <= mid) ans = max(ans, q4(lson, L, R, k));
if(R > mid) ans = max(ans, q4(rson, L, R, k));
return ans;
}
inline int q5(int rt, int l, int r, int L, int R, int k){
if(L <= l && r <= R) return nxt(tree[rt], k);
int mid = (l + r) >> 1;
int ans = inf;
if(L <= mid) ans = min(ans, q5(lson, L, R, k));
if(R > mid) ans = min(ans, q5(rson, L, R, k));
return ans;
}
int main(){
//freopen("E://123.in","r",stdin); //输入重定向,输入数据将从in.txt文件中读取
//freopen("E://oneout.txt","w",stdout); //输出重定向,输出数据将保存在out.txt文件中
int op, l, r, k, pos;
srand((ll)time(0));
n = read(); m = read();
for(int i = 1 ; i <= n ; ++ i){
a[i] = read();
}
build(1, 1, n);
while(m --){
op = read();
if(op == 1){
l = read(); r = read(); k = read();
write( q1(1, 1, n, l, r, k) + 1 ); putchar('\n');
}
else if(op == 2){
l = read(); r = read(); k = read();
int L = 0, R = 1e8, ans;
while(L <= R){
int mid = (L + R) >> 1;
if(q1(1, 1, n, l, r, mid) + 1 <= k) L = mid + 1, ans = mid;
else R = mid - 1;
}
write(ans); putchar('\n');
}
else if(op == 3){
pos = read(); k = read();
q3(1, 1, n, pos, k);
a[pos] = k;
}
else if(op == 4){
l = read(); r = read(); k = read();
write( q4(1, 1, n, l, r, k) ); putchar('\n');
}
else if(op == 5){
l = read(); r = read(); k = read();
write( q5(1, 1, n, l, r, k) ); putchar('\n');
}
}
return 0;
}
P3380 【模板】二逼平衡树(树套树)
最新推荐文章于 2019-12-03 19:56:20 发布