【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); }