Description
Input
Output
Sample Input
5 5
12 41 46 68 69
35 61 82 84 96
2 1 4 3 5
1 0 5 75
2 2 4 3 4
2 3 4 1 5
2 1 4 2 4
Sample Output
68
68
68
61
Data Constraint
Solution
一道梁正昊老师讲的分治专题的原题。
对于查询操作,每次去两个区间的中间数,i,j。
分类讨论一下。
1.如果a[ i ]<b[ j ]
即排序后a[l 1~i ]都排在b[ j ]前面
a.如果i+j<k,那么第k小数的一定不在 l1~ i 之间,所以可以将前i-l1+1去掉,求前k-(i-l1+1)个数。
b.如果i+j>=k,则第k小的数一定不在 j+1~r2 之间。
2.如果a[ i ]>=b[ j ]
即排序后b [l2~j ]都排在a[ i ]前面
a.如果i+j<k,那么第k小的数一定不在 l2~j 之间,将前面去掉,求前k-(l2-j+1)个数。
b.如果i+j>=k,那么第k小的数一定不在 i+1~r1 之间。
最后当l1==r1或者l2==r2时,我们将那一个独立的数在另一个区间排第几二分出来,最后就可以找出整个区间第k大的数了。
这样不断讲一个区间减半,因此一次查询是O(log 2n)的。
对于修改直接做就可以了。
时间复杂度O(m log n)。
Code
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define I int
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof(a))
#define N 500010
#define P(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
#define rt return
using namespace std;
void rd(I &x){
x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
I n,m,a[N],b[N],x,y,z,ans;
void solve(I l1,I r1,I l2,I r2,I k){
if(l1==r1){
I l=l2,r=r2,mid,s=k+1;
while(l<=r){
mid=(l+r)>>1;
if(b[mid]>a[l1]){s=mid-l2+1;r=mid-1;}
else l=mid+1;
}
if(s==k) ans=a[l1];
else if(s>k) ans=b[l2+k-1];
else ans=b[l2+k-2];
rt;
}
if(l2==r2){
I l=l1,r=r1,mid,s=k+1;
while(l<=r){
mid=(l+r)>>1;
if(a[mid]>b[l2]){s=mid-l1+1;r=mid-1;}
else l=mid+1;
}
if(s==k) ans=b[l2];
else if(s>k) ans=a[l1+k-1];
else ans=a[l1+k-2];
rt;
}
/*if(k==1){
ans=a[l1]<b[l2]?a[l1]:b[l2];rt;
}
if(l1>r1){
ans=b[l2+k-1];rt;
}
if(l2>r2){
ans=a[l1+k-1];rt;
}*///为什么会错?
I M1=(l1+r1)>>1,M2=(l2+r2)>>1;
if(a[M1]<b[M2]){
if(M1-l1+1+M2-l2+1<k) solve(M1+1,r1,l2,r2,k-(M1-l1+1));
else solve(l1,r1,l2,M2,k);
}
else{
if(M1-l1+1+M2-l2+1<k) solve(l1,r1,M2+1,r2,k-(M2-l2+1));
else solve(l1,M1,l2,r2,k);
}
}
I main(){
P("median");
rd(n);rd(m);
F(i,1,n) rd(a[i]);
F(i,1,n) rd(b[i]);
while(m--){
rd(x);
if(x==1){
rd(x),rd(y),rd(z);
if(x) b[y]=z;
else a[y]=z;
}
else{
I l1,r1,l2,r2,k;
rd(l1),rd(r1),rd(l2),rd(r2);
k=(r1-l1+1+r2-l2+1)/2+1;
solve(l1,r1,l2,r2,k);
printf("%d\n",ans);
}
}
rt 0;
}
作者:zsjzliziyang
QQ:1634151125
转载及修改请注明
本文地址:https://blog.youkuaiyun.com/zsjzliziyang/article/details/99709152