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

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

目录

HDU6040:传送门

(m(mleq 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<<"
"
#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("
");
  }
  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("
");
  }
  return 0;
}


####CSU2078:[传送门](http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2078)

感觉被针对了,就是过不去~~

原文地址:https://www.cnblogs.com/Cwolf9/p/9513199.html