您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继
对于操作1,2,4,5各输出一行,表示查询结果
1.n和m的数据范围:n,m<=50000
2.序列中每个数的数据范围:[0,1e8]
#include <iostream> #include <cstdio> #include <vector> #include <algorithm> #include <cmath> using namespace std; #define PB push_back const int N = 1005; const int INF = 0x3f3f3f3f; int SZ; int B_cnt; vector<int> B[N]; int a[N * N]; int query_rank(int L, int R, int x) { int ret = 0; --L, --R; int LB = L / SZ + 1; int RB = R / SZ; if(LB < RB) { for(int i = L; i < LB * SZ; ++i) { if(a[i] < x) ++ret; } for(int i = RB * SZ; i <= R; ++i) { if(a[i] < x) ++ret; } for(int i = LB; i < RB; ++i) { ret += lower_bound(B[i].begin(), B[i].end(), x) - B[i].begin(); } } else { for(int i = L; i <= R; ++i) { if(a[i] < x) ++ret; } } return ret + 1; } bool ok(int x, int L, int R, int rank) { return query_rank(L, R, x + 1) - 1 >= rank; } void query_x(int L, int R, int rank) { int l = 0, r = 1e8 + 5; while(l < r) { int mid = (l + r) >> 1; if(ok(mid, L, R, rank)) r = mid; else l = mid + 1; } printf("%d\n", r); } void update(int p, int x) { --p; int tmp = a[p]; a[p] = x; int bl = p / SZ; int pos = lower_bound(B[bl].begin(), B[bl].end(), tmp) - B[bl].begin(); B[bl][pos] = x; sort(B[bl].begin(), B[bl].end()); } int query_pre(int L, int R, int x) { int ret = 0; --L, --R; int LB = L / SZ + 1; int RB = R / SZ; if(LB < RB) { for(int i = L; i < LB * SZ; ++i) { if(a[i] < x) ret = max(ret, a[i]); } for(int i = RB * SZ; i <= R; ++i) { if(a[i] < x) ret = max(ret, a[i]); } for(int i = LB; i < RB; ++i) { int pos = lower_bound(B[i].begin(), B[i].end(), x) - B[i].begin() - 1; if(pos >= 0) ret = max(ret, B[i][pos]); } } else { for(int i = L; i <= R; ++i) { if(a[i] < x) ret = max(ret, a[i]); } } return ret; } int query_nxt(int L, int R, int x) { int ret = INF; --L, --R; int LB = L / SZ + 1; int RB = R / SZ; if(LB < RB) { for(int i = L; i < LB * SZ; ++i) { if(a[i] > x) ret = min(ret, a[i]); } for(int i = RB * SZ; i <= R; ++i) { if(a[i] > x) ret = min(ret, a[i]); } for(int i = LB; i < RB; ++i) { int pos = upper_bound(B[i].begin(), B[i].end(), x) - B[i].begin(); if(pos < B[i].size()) ret = min(ret, B[i][pos]); } } else { for(int i = L; i <= R; ++i) { if(a[i] > x) ret = min(ret, a[i]); } } return ret; } int main() { int n, m; scanf("%d%d", &n, &m); SZ = sqrt(n) + 1; B_cnt = n / SZ; for(int i = 0 ; i < n; ++i) { int x; scanf("%d", &a[i]); int bl = i / SZ; B[bl].PB(a[i]); } for(int i = 0; i <= B_cnt; ++i) { sort(B[i].begin(), B[i].end()); } for(int i = 0; i < m; ++i) { int op, a, b, c; scanf("%d", &op); if(op == 1) { scanf("%d%d%d", &a, &b, &c); printf("%d\n", query_rank(a, b, c)); } else if(op == 2) { scanf("%d%d%d", &a, &b, &c); query_x(a, b, c); } else if(op == 3) { scanf("%d%d", &a, &b); update(a, b); } else if(op == 4) { scanf("%d%d%d", &a, &b, &c); printf("%d\n", query_pre(a, b, c)); } else if(op == 5) { scanf("%d%d%d", &a, &b, &c); printf("%d\n", query_nxt(a, b, c)); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/whai362/article/details/48104219