https://vjudge.net/problem/HDU-5649
题意:一个n的排列,然后执行Q次操作,每次操作是对某个区间从小到大排序或者是从大到小排序。最后只查询一次,输出第k个位置当前的数。
思路:
这个题只查询了一次,所以有了特殊的解法。
我们二分答案,直接枚举最后的答案。
然后把原来的数列中 大于等于这个答案的置为一,小于这个答案的职位零,然后用线段树操作,
就成了 区间修改, 升序, 把区间的1 放后面,,降序,把区间的 1 放前面。
最后看看我们要查的那个位置,是1 的话就说明枚举的有可能大了,,反之就是小了。
写代码的时候,出现了错误,就是左区间的值大于右区间的值。
如果全是 0 或者全是1 的情况下,会出现左区间大于右区间。
#include
#define mem(x,v) memset(x,v,sizeof(x))
#define go(i,a,b) for (int i = a; i <= b; i++)
#define og(i,a,b) for (int i = a; i >= b; i--)
using namespace std;
typedef long long LL;
const double EPS = 1e-10;
const int INF = 0x3f3f3f3f;
const int N = 1e5+10;
struct segtree{
int l,r,lazy,val;
}f[N*4];
int n,m,s[N],t[N],a[N],b[N],c[N],kk;
void push_down(int now){
if (f[now].lazy == -1) return;
f[now*2].val = (f[now*2].r - f[now*2].l)*f[now].lazy;
f[now*2+1].val = (f[now*2+1].r - f[now*2+1].l)*f[now].lazy;
f[now*2].lazy = f[now].lazy;
f[now*2+1].lazy = f[now].lazy;
f[now].lazy = -1;
return;
}
void build(int now, int l, int r){
f[now].l = l; f[now].r = r; f[now].lazy = -1;
if (r - l == 1){
f[now].val = t[l]; return;
}
int m = (l + r)/2;
build(now*2,l,m);
build(now*2+1,m,r);
f[now].val = f[now*2].val + f[now*2+1].val; return;
}
void Insert(int now, int l, int r, int op){
if (l > r) return;
if (l <= f[now].l && r >= f[now].r - 1){
f[now].val = (f[now].r - f[now].l) * op;
f[now].lazy = op;
return;
}
push_down(now);
int m = (f[now].r + f[now].l) / 2;
if (l < m) Insert(now*2,l,r,op);
if (r >= m) Insert(now*2+1,l,r,op);
f[now].val = f[now*2].val + f[now*2+1].val;
return;
}
int Qurey(int now, int l, int r){
int ans = 0;
if (l <= f[now].l && r >= f[now].r-1){
return f[now].val;
}
push_down(now);
int m = (f[now].l + f[now].r) / 2;
if (l < m) ans += Qurey(now*2,l,r);
if (r >= m) ans += Qurey(now*2+1,l,r);
return ans;
}
bool find(int mid){
go(i,1,n) if (s[i] >= mid) t[i] = 1; else t[i] = 0;
build(1,1,n+1);
go(i,1,m){
int k = Qurey(1,b[i],c[i]);
if (a[i] == 0) Insert(1,b[i],c[i]-k,0),Insert(1,c[i]-k+1,c[i],1);
if (a[i] == 1) Insert(1,b[i],b[i]+k-1,1),Insert(1,b[i]+k,c[i],0);
}
return Qurey(1,kk,kk);
}
int main(){
int T; cin>>T;
while(T--) {
scanf("%d%d",&n,&m);
go(i,1,n) scanf("%d",&s[i]);
go(i,1,m) scanf("%d%d%d",&a[i],&b[i],&c[i]);
scanf("%d",&kk);
int l = 0, r = n+1,ans = -1;
while(l <= r){
int mid = (l + r)/2;
if (find(mid)) {l = mid + 1; ans = mid; } else r = mid - 1;
}
printf("%d\n",ans);
}
return 0;
}