O(n)线性时间求解第k大-HDU6040-CSU2078

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

目录

HDU6040

传送门
m ( m ≤ 100 ) m(m\leq 100) m(m100)次查询长度为 n ( n ≤ 1 e 7 ) n(n \leq 1e7) n(n1e7)区间的第k大。

思路

  • 利用快排的partation思想求解,但是要注意剪枝
  • 就是标记一下被确定好位置的地方
  • 然后这个题还可以用 s t l stl stl n t h _ e l e m e n t nth\_element nth_element水过
  • n t h _ e l e m e n t 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;
}

n t h _ e l e m e n t nth\_element 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

传送门

要加读入挂才能过。

HDU1425

int qs(int l, int r) {
    if(l >= r)return l;
    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]);
    return a;
}
void qsort(int l, int r) {
    if(l >= r) return ;
    int partition = qs(l, r);
    qsort(l, partition - 1);
    qsort(partition + 1, r);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值