【luogu3834】【POJ2104】【模板】可持久化线段树 1 [主席树]
改了一上午改到怀疑人生,结果是因为这个,好像是直接用快读那样进去容易炸,多打一点也费不了多少时间,平平淡淡才是真
printf("%d\n",b[query(1,size,rt[rd()-1],rt[rd()],rd())]);
好像数组大小有窍门,然而我并没有管就开了那么大,好像什么什么乘40
emmm洛谷测试出来是这样的
然后是poj
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=200000+10; 4 #define lson l,mid 5 #define rson mid+1,r 6 int n,m,a[N],b[N],cnt=0;//a原 b离散后 7 int rt[N]; 8 //根节点 左子树下标 右子树下标 个数 9 struct lxyy 10 { 11 int l,r,sum; 12 }t[N<<5]; 13 14 inline int rd() 15 { 16 int x=0,w=0;char ch=0; 17 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 18 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 19 return w?-x:x; 20 } 21 22 int build(int l,int r)// 23 { 24 int rtt=++cnt; 25 if(l<r) 26 { 27 int mid=(l+r)>>1; 28 t[rtt].l=build(lson); 29 t[rtt].r=build(rson); 30 } 31 return rtt; 32 } 33 34 int update(int l,int r,int pre,int x) 35 {//左右 前一个 修改点 36 int rtt=++cnt; 37 t[rtt].l=t[pre].l,t[rtt].r=t[pre].r,t[rtt].sum=t[pre].sum+1; 38 if(l==r) return rtt; 39 int mid=(l+r)>>1; 40 if(x<=mid) t[rtt].l=update(lson,t[rtt].l,x);//在左区间 41 else t[rtt].r=update(rson,t[rtt].r,x);//在右区间 42 return rtt; 43 } 44 45 int query(int l,int r,int u,int v,int k) 46 {//查询区间 区间 第k大 47 if(l==r) return l; 48 int mid=(l+r)>>1,x=t[t[v].l].sum-t[t[u].l].sum; 49 if(x>=k) return query(lson,t[u].l,t[v].l,k);//左区间 50 else return query(rson,t[u].r,t[v].r,k-x);//右区间 51 } 52 53 int main() 54 { 55 n=rd(),m=rd(); 56 for(int i=1;i<=n;i++) 57 a[i]=rd(),b[i]=a[i]; 58 sort(b+1,b+1+n); 59 int size=unique(b+1,b+1+n)-b-1; 60 rt[0]=build(1,size); 61 for(int i=1;i<=n;i++) 62 { 63 a[i]=lower_bound(b+1,b+size+1,a[i])-b;// 64 rt[i]=update(1,size,rt[i-1],a[i]); 65 } 66 while(m--) 67 { 68 int x=rd(),y=rd(),k=rd(); 69 printf("%d\n",b[query(1,size,rt[x-1],rt[y],k)]); 70 } 71 // printf("%d\n",b[query(1,size,rt[rd()-1],rt[rd()],rd())]);//万恶之源 72 return 0; 73 }
vector
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=200000+10; 4 #define lson l,mid 5 #define rson mid+1,r 6 int n,m,a[N],rt[N],cnt=0;//a原 7 vector<int> b; 8 struct lxyy 9 { 10 int l,r,sum;//根节点 左子树下标 右子树下标 个数 11 }t[N*40]; 12 13 inline int rd() 14 { 15 int x=0,w=0;char ch=0; 16 while(!isdigit(ch)) w|=ch=='-',ch=getchar(); 17 while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 18 return w?-x:x; 19 } 20 21 void update(int l,int r,int &x,int pre,int pos) 22 {//左右 当前 前一个 修改点 23 t[++cnt].l=t[pre].l,t[cnt].r=t[pre].r,t[cnt].sum=t[pre].sum+1; 24 x=cnt; 25 if(l==r) return; 26 int mid=(l+r)>>1; 27 if(pos<=mid) update(lson,t[x].l,t[pre].l,pos);//在左区间 28 else update(rson,t[x].r,t[pre].r,pos);//在右区间 29 } 30 31 int query(int l,int r,int u,int v,int k) 32 {//查询区间 区间 第k大 33 if(l==r) return l; 34 int mid=(l+r)>>1,x=t[t[v].l].sum-t[t[u].l].sum; 35 if(x>=k) return query(lson,t[u].l,t[v].l,k);//左区间 36 else return query(rson,t[u].r,t[v].r,k-x);//右区间 37 } 38 39 int main() 40 { 41 n=rd(),m=rd(); 42 for(int i=1;i<=n;i++) 43 a[i]=rd(),b.push_back(a[i]); 44 sort(b.begin(),b.end()); 45 b.erase(unique(b.begin(),b.end()),b.end()); 46 for(int i=1;i<=n;i++) 47 { 48 int pos=lower_bound(b.begin(),b.end(),a[i])-b.begin()+1; 49 update(1,n,rt[i],rt[i-1],pos); 50 } 51 while(m--) 52 { 53 int x=rd(),y=rd(),k=rd(); 54 printf("%d\n",b[query(1,n,rt[x-1],rt[y],k)-1]); 55 } 56 return 0; 57 }