【POJ2104】K-th Number

思路

  之前知道这道题是用<del>时代的眼泪</del>划分树写的TAT好复杂我看不懂

  然后主席就来拯救大家啦~\(≧▽≦)/~

  学了这么久还不会主席树QAQ今天才学的,又T又W的搞得我要死。。

  然后学到了离散化的新写法,不需要用Map。。

  基本思想就是针对[1,L]的每一个L开一个线段树,记录下[1,L]中每一个数出现的次数。

  然后L+1可以利用L的绝大部分点,不同的点重新开就好了。

  查询很好查,就跟Splay一样。

  

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#include <vector>
#include <ctime>
#include <functional>
#define pritnf printf
#define scafn scanf
#define sacnf scanf
#define For(i,j,k) for(int i=(j);i<=(k);(i)++)
#define Clear(a) memset(a,0,sizeof(a))
using namespace std;
typedef unsigned int Uint;
const int INF=0x3fffffff;
const double eps=1e-10;
///==============struct declaration==============
struct Node{
   Node *lc,*rc;
   int sum;
   Node (){lc=rc=NULL;sum=0;}
};
///==============var declaration=================
const int MAXN=100010;
Node Poor[MAXN*30];int top=0;
//#define new(Node) (&Poor[++top])
int n,m,tot=0,k,v;
int A[MAXN],Sorted[MAXN];
int Id[MAXN];
map <int,int> Mp;
Node *Seg_Tree[MAXN],*null;
///==============function declaration============
void Add_Seg(Node *&L,Node *&R,int l,int r);
void Query(Node *&prev,Node *&o,int Rank,int l,int r);
void update(Node *&o,int l,int r);
///==============main code=======================
int main()
{
#define FILE__
#ifdef FILE__
   freopen("input.txt","r",stdin);
   freopen("output.txt","w",stdout);
#endif 
   scanf("%d%d",&n,&m);
   for(int i=1;i<=n;i++){
      scanf("%d",A+i);
      Sorted[i]=A[i];
   }
   null=new(Node);
   null->sum=0,null->lc=null,null->rc=null;
   sort(Sorted+1,Sorted+1+n);
   tot=unique(Sorted,Sorted+1+n)-Sorted-1;
   Seg_Tree[0]=new(Node);
   for(int i=1;i<=n;i++){
      Seg_Tree[i]=new(Node);   
      k=A[i];v=1;
      Add_Seg(Seg_Tree[i-1],Seg_Tree[i],1,tot);
   }
   while (m--){
      int L,R,K;scanf("%d%d%d",&L,&R,&K);
      Query(Seg_Tree[L-1],Seg_Tree[R],K,1,tot);
   }
   return 0;
}
///================fuction code====================
void Add_Seg(Node *&prev,Node *&o,int l,int r){
   int m=(l+r)>>1;
   if (prev==NULL) prev=null;
   if (o==NULL) o=new(Node);
   if (l==r)
      o->sum=v+prev->sum;
   else{
      if (Sorted[m]>=k){
         o->rc=prev->rc;
         o->lc=new(Node);
         Add_Seg(prev->lc,o->lc,l,m);
      }  
      else{
         o->lc=prev->lc;
         o->rc=new(Node);
         Add_Seg(prev->rc,o->rc,m+1,r);
      }
      update(o,l,r);
   }
}
void update(Node *&o,int l,int r){
   o->sum=0;
   if (o->lc!=NULL)  o->sum+=o->lc->sum;
   if (o->rc!=NULL)  o->sum+=o->rc->sum;
}
void Query(Node *&L,Node *&R,int Rank,int l,int r){
   if (L==NULL) L=null;
   if (R==NULL) R=null;
   int Lsum=0,m=(l+r)>>1;
   if (l==r){
      printf("%d\n",Sorted[l]);
      return ;
   }
   if (R->lc!=NULL)  Lsum+=R->lc->sum;
   if (L->lc!=NULL)  Lsum-=L->lc->sum;
   if (Lsum>=Rank)
      Query(L->lc,R->lc,Rank,l,m);
   else
      Query(L->rc,R->rc,Rank-Lsum,m+1,r);
}
POJ2104

 

posted @ 2015-03-18 16:50  Houjikan  阅读(205)  评论(0编辑  收藏  举报