O(n)线性时间求解第k大-HDU6040-CSU2078
(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
目录
HDU6040:传送门
\(m(m\leq 100)\)次查询长度为\(n(n \leq 1e7)\)区间的第k大。
思路
- 利用快排的partation思想求解,但是要注意剪枝
- 就是标记一下被确定好位置的地方
- 然后这个题还可以用\(stl\)的\(nth\_element\)水过
- \(nth\_element\)我没有剪枝就是暴力然后抠常数水过去了哈哈
AC代码:
partation思想
#pragma comment(linker,"/STACK:102400000,102400000")
#include <bits/stdc++.h>
#define mme(a,b) memset((a),(b),sizeof((a)))
#define fuck(x) cout<<"* "<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const double eps = 1e-8;
const int N = 1e7 + 7;
const int MX = 2e6 + 7;
int n, m;
unsigned x, y, z,ar[N],ans[N];
int br[N], cr[N];
inline unsigned rng61(){
unsigned t;
x ^= x << 16;
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y;
y = z;
z = t ^ x ^ y;
return z;
}
int vis[N];
void qs(int l,int r,int k){
if(l>=r)return;
int a=l,b=r;
while(a<b){
while(a<b&&ar[b]>=ar[l])--b;
while(a<b&&ar[a]<=ar[l])++a;
swap(ar[a],ar[b]);
}
swap(ar[a],ar[l]);
vis[a]=1;
if(a==k)return;
if(a<k)qs(a+1,r,k);
else qs(l,a-1,k);
}
int main(){
int tim,tc=0;
while(~scanf("%d%d%u%u%u",&n,&m,&x,&y,&z)){
for(int i=0;i<n;++i){
ar[i]=rng61();
vis[i]=0;
}
for(int i=0;i<m;++i){
scanf("%d",&br[i]);
cr[i]=br[i];
}
sort(cr,cr+m);
int k = unique(cr,cr+m)-cr,last=n-1;
for(int i=k-1;i>=0;--i){
int l=cr[i],r=cr[i];
while(l>=0&&vis[l]==0)--l;
while(r<n&&vis[r]==0)++r;
++l;--r;
qs(l,r,cr[i]);
ans[cr[i]]=ar[cr[i]];
}
printf("Case #%d:", ++tc);
for(int i=0;i<m;++i){
printf(" %u", ans[br[i]]);
}
printf("\n");
}
return 0;
}
$nth\_element$
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e7 + 7;
int n, m;
unsigned x, y, z,ar[N],ans[N];
int br[N], cr[N];
inline unsigned rng61(){
unsigned t;
x ^= x << 16;
x ^= x >> 5;
x ^= x << 1;
t = x;
x = y;
y = z;
z = t ^ x ^ y;
return z;
}
int main(){
int tim,tc=0;
while(~scanf("%d%d%u%u%u",&n,&m,&x,&y,&z)){
for(int i=0;i<n;++i){
ar[i]=rng61();
}
for(int i=0;i<m;++i){
scanf("%d",&br[i]);
cr[i]=br[i];
}
sort(cr,cr+m);
int k = unique(cr,cr+m)-cr;
for(int i=k-1;i>=0;--i){
nth_element(ar,ar+cr[i],ar+n);
ans[cr[i]]=ar[cr[i]];
}
printf("Case #%d:", ++tc);
for(int i=0;i<m;++i){
printf(" %u", ans[br[i]]);
}
printf("\n");
}
return 0;
}
####CSU2078:[传送门](http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2078)
感觉被针对了,就是过不去~~
ACMer,无怨无悔