HDU 2665

第一次写归并排序+线段树 感觉受益颇深
这道题是求在[s,t]区间内的第k大元素 
首先使用归并排序可以每次得到任意2^n区间内的有序状态
在此基础上使用线段树分离区间
最后二分有序数列上的元素,直到查找到的元素符合条件为止.
 
 
#include <iostream>
using namespace std;

typedef 
struct  
{
    
int low,high;
    
int dp;
}
node;

const int MAXN=100020;
const int Lmax=INT_MAX;

node Tree[MAXN
<<2];
int hash[22][MAXN];


inline 
void Msort(int ind,int dp,int low,int high)
{
    Tree[ind].dp
=dp;
    Tree[ind].low
=low;
    Tree[ind].high
=high;

    
if (Tree[ind].low==Tree[ind].high)
    
{
        
return;
    }


    
int mid=(low+high)>>1;

    Msort(ind
<<1,dp+1,low,mid);
    Msort((ind
<<1)+1,dp+1,mid+1,high);


    
int i,j;
    
int inds=low;

    
for (i=low,j=mid+1;i<=mid&&j<=high;)
    
{
        
if (hash[dp+1][i]<hash[dp+1][j])
        
{
            hash[dp][inds
++]=hash[dp+1][i++];
        }

        
else
        
{
            hash[dp][inds
++]=hash[dp+1][j++];
        }

        
    }


    
if (i<=mid)
    
{
        
for (;i<=mid;)
        
{
            hash[dp][inds
++]=hash[dp+1][i++];
        }

    }


    
if (j<=high)
    
{
        
for (;j<=high;)
        
{
            hash[dp][inds
++]=hash[dp+1][j++];
        }

    }


}



inline 
int rank(int ind,int res,int low,int high)
{
    
int dp=Tree[ind].dp;

    
int mid,rs=low-1;

    
while (low<=high)
    
{
        mid
=(low+high)>>1;
        
        
if (hash[dp][mid]<res)
        
{
            rs
=mid,low=mid+1;
        }

        
else
        
{
            high
=mid-1;
        }

    }

    
return rs-Tree[ind].low+1;
}


inline 
int query(int ind,int res,int low,int high)
{
    
if (Tree[ind].low==low&&Tree[ind].high==high)
    
{
        
return rank(ind,res,low,high);
    }


    
int mid=(Tree[ind].low+Tree[ind].high)>>1;

    
if (low>mid)
    
{
        
return query((ind<<1)+1,res,low,high);
    }


    
if (high<=mid)
    
{
        
return query(ind<<1,res,low,high);
    }

    

    
return query(ind<<1,res,low,mid)+query((ind<<1)+1,res,mid+1,high);

}


inline 
bool check(int res,int low,int high,int k)
{
    
int rs=query(1,res,low,high);
    
return rs<k;
}


int main()
{
    
int T;
    scanf(
"%d",&T);

    
while (T--)
    
{
        
int n,m;
        
int s,t,k;
        scanf(
"%d%d",&n,&m);

        
int i;

        
for (i=1;i<=n;++i)
        
{
            scanf(
"%d",&hash[0][i]);
        }


        
int c=n-1;
        
int dp=0;

        
while (c)
        
{
            c
>>=1;
            
++dp;
        }


        
for (i=dp;i>=0&&i>=dp-2;--i)
        
{
            memcpy(hash[i]
+1,hash[0]+1,n<<2);
        }


        Msort(
1,0,1,n);

        
int low,high,res;

        
while(m--)
        
{
            scanf(
"%d%d%d",&s,&t,&k);
            low
=1,high=n,res=Lmax;

            
while (low<=high)
            
{
                
int mid=(low+high)>>1;

                
if (check(hash[0][mid],s,t,k))
                
{
                    res
=mid;
                    low
=mid+1;
                }

                
else
                
{
                    high
=mid-1;    
                }


            }

            printf(
"%d\n",hash[0][res]);
        }



    }

    
return 0;
}
 
posted @ 2009-03-11 11:08  Hdu-Lost  阅读(952)  评论(3编辑  收藏  举报