zoukankan      html  css  js  c++  java
  • [noi32]sort

    先解释一下checker.cpp,它的判定标准是2e7,即答案超过2e7就认为代价过大了。

    首先,很容易想到的办法是直接对其快排,从外到内交换区间即可,然而这样会被邪恶的出题人给卡掉(当然其实随便一组大数据都能卡)。

    由于一次操作可以翻转而不仅仅是交换,所以要将一个区间分成两块仅仅需要经左右两个区间都分成两块后对中间进行一个翻转即可。

    来分析一下这种做法的代价:计将一个长度为l区间分成两块的代价为T(l),那么有递推式T(l)=2T(l/2)+l,即$T(l)=l\ log_{2}l$。然后计将一个长度为l的区间排好序的代价为T’(l),有递推式$T'(l)=2T'(l/2)+T(l)=2T'(l/2)+l\ log_{2}l$,解得$T'(l)=l\ log_{2}^{2}l$,即总代价(或者说总时间复杂度)为$o(l\ log_{2}^{2}l)$,看上去似乎差不多就是2e7,但实际上是可以通过的

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mid (l+r>>1)
     4 map<int,int>mat;
     5 int n,a[50001],b[50001];
     6 void rev(int l,int r,int k){
     7     if (l==r)return;
     8     rev(l,mid,k);
     9     rev(mid+1,r,k);
    10     int i=mid+1,j=mid;
    11     while ((i>l)&&(a[i-1]>k))i--;
    12     while ((j<r)&&(a[j+1]<=k))j++;
    13     if (i<j)printf("%d %d\n",i,j);
    14     reverse(a+i,a+j+1);
    15 }
    16 void kspx(int l,int r){
    17     if (l==r)return;
    18     rev(l,r,mid);
    19     kspx(l,mid);
    20     kspx(mid+1,r);
    21 }
    22 int main(){
    23     scanf("%d",&n);
    24     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    25     memcpy(b,a,sizeof(b));
    26     sort(b+1,b+n+1);
    27     for(int i=1;i<=n;i++)mat[b[i]]=i;
    28     for(int i=1;i<=n;i++)a[i]=mat[a[i]]--;
    29     kspx(1,n);
    30     printf("-1 -1");
    31 }
    View Code
  • 相关阅读:
    BZOJ2219数论之神——BSGS+中国剩余定理+原根与指标+欧拉定理+exgcd
    Luogu 3690 Link Cut Tree
    CF1009F Dominant Indices
    CF600E Lomsat gelral
    bzoj 4303 数列
    CF1114F Please, another Queries on Array?
    CF1114B Yet Another Array Partitioning Task
    bzoj 1858 序列操作
    bzoj 4852 炸弹攻击
    bzoj 3564 信号增幅仪
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11272212.html
Copyright © 2011-2022 走看看