同一份数据,程序有时候会卡死,有时候却运行正常
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
const int maxn = 5e5 + 5,inf = 2147483647;
int n,m,tot;
int w[maxn];
int ch[maxn][2],val[maxn],pri[maxn],siz[maxn];
int pushup(int now)
{
siz[now] = siz[ch[now][0]] + siz[ch[now][1]] + 1;
}
int new_node(int v)
{
siz[++tot] = 1;
val[tot] = v;
pri[tot] = rand();
return tot;
}
int merge(int x,int y)
{
//cout<<x<<' '<<y<<endl;
if(!x || !y) return x + y;
if(pri[x] < pri[y])
{
//cout<<pri[x]<<' '<<pri[y]<<endl;
ch[x][1] = merge(ch[x][1],y);
pushup(x);
return x;
}
else
{
//cout<<pri[x]<<' '<<pri[y]<<endl;
ch[y][0] = merge(x,ch[y][0]);
pushup(y);
return y;
}
}
void split(int now,int k,int &x,int &y)
{
//cout<<1<<endl;
if(!now) x = y = 0;
else
{
if(val[now] <= k) x = now,split(ch[now][1],k,ch[now][1],y);
else y = now,split(ch[now][0],k,x,ch[now][0]);
pushup(now);
}
}
int get_k(int now,int k)
{
while(1)
{
if(k <= siz[ch[now][0]]) now = ch[now][0];
else if(k == siz[ch[now][0]] + 1) return now;
else k -= siz[ch[now][0]] + 1,now = ch[now][1];
}
}
int rak(int &root,int v)
{
int x,y;
split(root,v - 1,x,y);
int ans = siz[x] + 1;
root = merge(x,y);
//cout<<ans<<endl;
return ans;
}
void insert(int &root,int v)
{
int x,y;
split(root,v,x,y);
root = merge(merge(x,new_node(v)),y);
}
void del(int &root,int v)
{
int x,y,z;
split(root,v,x,z);
split(root,v - 1,x,y);
y = merge(ch[y][0],ch[y][1]);
root = merge(merge(x,y),z);
}
void update(int &root,int v,int k)
{
del(root,v);
insert(root,k);
}
int get_pre(int &root,int v)
{
int x,y;
split(root,v - 1,x,y);
int ans = val[get_k(x,siz[x])];
root = merge(x,y);
return ans;
}
int get_suc(int &root,int v)
{
int x,y;
split(root,v,x,y);
int ans = val[get_k(y,1)];
root = merge(x,y);
return ans;
}
int L[maxn],R[maxn],T[maxn];
void build(int u,int l,int r)
{
L[u] = l,R[u] = r;
insert(T[u],-inf),insert(T[u],inf);
//cout<<T[u];
int mid = (l + r) / 2;
for(int i = l; i <= r; i++) insert(T[u],w[i]);
if(l == r) return ;
build(u * 2,l,mid),build(u * 2 + 1,mid + 1,r);
}
int query(int u,int a,int b,int x)
{
//cout<<L[u]<<' '<<R[u]<<' '<<a<<' '<<b<<endl;
if(L[u] >= a && R[u] <= b)
{
//cout<<1;
return rak(T[u],x) - 1;
}
int mid = (L[u] + R[u]) / 2,res = 0;
if(a <= mid) res += query(u * 2,a,b,x);
if(b > mid) res += query(u * 2 + 1,a,b,x);
return res;
}
void change(int u,int p,int x)
{
update(T[u],w[p],x);
if(L[u] == R[u]) return ;
int mid = (L[u] + R[u]) / 2;
if(p <= mid) change(u * 2,p,x);
else change(u * 2 + 1,p,x);
}
int query_pre(int u,int a,int b,int x)
{
if(L[u] >= a && R[u] <= b) return get_pre(T[u],x);
int mid = (L[u] + R[u]) / 2,res = -inf;
if(a <= mid) res = max(res,query_pre(u * 2,a,b,x));
if(b > mid) res = max(res,query_pre(u * 2 + 1,a,b,x));
return res;
}
int query_suc(int u,int a,int b,int x)
{
if(L[u] >= a && R[u] <= b) return get_suc(T[u],x);
int mid = (L[u] + R[u]) / 2,res = inf;
if(a <= mid) res = min(res,query_suc(u * 2,a,b,x));
if(b > mid) res = min(res,query_suc(u * 2 + 1,a,b,x));
return res;
}
int main()
{
srand((unsigned)time(NULL));
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
{
scanf("%d",&w[i]);
}
build(1,1,n);
for(int i = 1; i <= m; i++)
{
int op,a,b,x;
scanf("%d",&op);
if(op == 1)
{
scanf("%d%d%d",&a,&b,&x);
printf("%d\n",query(1,a,b,x) + 1);
}
else if(op == 2)
{
scanf("%d%d%d",&a,&b,&x);
int l = 0,r = 1e8;
while(l < r)
{
int mid = (l + r + 1) / 2;
if(query(1,a,b,mid) + 1 <= x) l = mid;
else r = mid - 1;
}
printf("%d\n",r);
}
else if(op == 3)
{
scanf("%d%d",&a,&x);
change(1,a,x);
w[a] = x;
}
else if(op == 4)
{
scanf("%d%d%d",&a,&b,&x);
printf("%d\n",query_pre(1,a,b,x));
}
else
{
scanf("%d%d%d",&a,&b,&x);
printf("%d\n",query_suc(1,a,b,x));
}
}
return 0;
}