例题:poj2761
题目要求:给定一个长度为n的序列,给定m个询问,每次询问求[l,r]区间内的第k大;
对于这道题目来说,很多算法都可以使用,比如说树套树(一个负责划分区间,一个负责维护这段区间内的信息),主席树等;
对这道题我使用的是主席树;
主席树对付区间第k大是很优秀的,代码短,而且常数小;
主席树的主要功能是,建立n颗范围是1-i的权值线段树,对两颗线段树做差,就可以任意一个区间内的权值线段树;
详细看代码:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<set> #include<map> #include<queue> #include<algorithm> #include<iomanip> #include<stack> using namespace std; #define FILE "dealing" #define up(i,j,n) for(int i=(j);i<=(n);i++) #define pii pair<int,int> #define LL int #define mem(f,g) memset(f,g,sizeof(f)) namespace IO{ char buf[1<<15],*fs,*ft; int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;} int read(){ int ch=gc(),f=0,x=0; while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();} return f?-x:x; } int readint(){ int ch=getchar(),f=0,x=0; while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?-x:x; } }using namespace IO; const int maxn=101000<<5,inf=1000000000; int n,m,c[maxn]; struct node{ int k,id; bool operator<(const node b)const{return k<b.k;} }a[maxn]; namespace chair_tree{ int c[maxn][2],sum[maxn],cnt=0,rt[maxn],d; #define mid ((l+r)>>1) void updata(int o){sum[o]=sum[c[o][0]]+sum[c[o][1]];} void insert(int key,int pre,int& o,int l,int r){ if(!o)o=++cnt; if(l==r){sum[o]=1;return;} d=key>mid; c[o][d^1]=c[pre][d^1]; insert(key,c[pre][d],c[o][d],d?mid+1:l,d?r:mid); updata(o); } void init(int *a,int n){up(i,1,n)insert(a[i],rt[i-1],rt[i],1,n);} int query(int l,int r,int x,int y,int k){ if(l==r)return l; d=sum[c[y][0]]-sum[c[x][0]]; if(k<d)return query(l,mid,c[x][0],c[y][0],k); else return query(mid+1,r,c[x][1],c[y][1],k-d); } int Query(int l,int r,int k){return query(1,n,rt[l-1],rt[r],k-1);} }; int main(){ n=read(),m=read(); up(i,1,n)a[i].k=read(),a[i].id=i; sort(a+1,a+n+1); up(i,1,n)c[a[i].id]=i; chair_tree::init(c,n); int l,r,k; int pre=0,q=(1<<8)-1; while(m--){ l=read(),r=read(),k=read(); l^=(pre&q),r^=(pre&q); if(!l)l=1;if(!r)r=1; if(l>r)swap(l,r); printf("%d ",pre=a[chair_tree::Query(l,r,k)].k); } return 0; }