标签:div printf ret span air 处理 sub ref bsp
题解思路:首先按数组中的下标建一棵线段树,假设原数组是a,我们用一个新数组b记录a,将b数组先按权值排序、再按下标排序,然后再用数组记录m次询问,按k从小到大排序,再对每个询问二分线段树右边界,最后把m次询问按原来的顺序排回来,最后按顺序输出答案即可。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> PII; #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 const int MAXN = 2e5+10; const double EPS = 1e-12; int T,n,m; int sum[MAXN<<2]; struct A{ int x,pos; }a[MAXN],b[MAXN]; struct node{ int k,pp,id,ans; }q[MAXN]; inline void Update(int l,int r,int rt,int pos){ if(pos==l&&l==r){ sum[rt]=1; return ; } int mid=(l+r)/2; if(pos<=mid)Update(ls,pos); else Update(rs,pos); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } inline int Query(int l,int r,int rt,int pos){ if(pos>=r)return sum[rt]; int mid=(l+r)/2; int ans=0; ans+=Query(ls,pos); if(pos>mid)ans+=Query(rs,pos); return ans; } bool cmp1(A aa,A bb){ if(aa.x!=bb.x)return aa.x>bb.x; else return aa.pos<bb.pos; } bool cmp2(node aa,node bb){ return aa.k<bb.k; } bool cmp3(node aa,node bb){ return aa.id<bb.id; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); a[i].pos=i; b[i]=a[i]; } sort(b+1,b+n+1,cmp1); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d %d",&q[i].k,&q[i].pp); q[i].id=i; } sort(q+1,q+m+1,cmp2); int now=1; for(int i=1;i<=m;i++){ for(int j=now;j<=q[i].k;j++)Update(1,n,1,b[j].pos); now=q[i].k+1; int l=1,r=n,k; while(l<=r){ int mid=(l+r)/2; if(Query(1,n,1,mid)<q[i].pp)l=mid+1; else { r=mid-1; k=mid; } } q[i].ans=a[k].x; } sort(q+1,q+m+1,cmp3); for(int i=1;i<=m;i++)printf("%d\n",q[i].ans); }
悄悄说一句,其实没必要二分,二分的log完全可以去掉...
这里放一份去掉二分的代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> PII; #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 const int MAXN = 2e5+10; const double EPS = 1e-12; int T,n,m; int sum[MAXN<<2]; struct A{ int x,pos; }a[MAXN],b[MAXN]; struct node{ int k,pp,id,ans; }q[MAXN]; inline void Update(int l,int r,int rt,int pos){ if(pos==l&&l==r){ sum[rt]=1; return ; } int mid=(l+r)/2; if(pos<=mid)Update(ls,pos); else Update(rs,pos); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } inline int Query(int l,int r,int rt,int k){ if(l==r)return a[l].x; int mid=(l+r)/2; if(sum[rt<<1]>=k)return Query(ls,k); else return Query(rs,k-sum[rt<<1]); } bool cmp1(A aa,A bb){ if(aa.x!=bb.x)return aa.x>bb.x; else return aa.pos<bb.pos; }
bool cmp2(node aa,node bb){ return aa.k<bb.k; }
bool cmp3(node aa,node bb){ return aa.id<bb.id; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i].x); a[i].pos=i; b[i]=a[i]; } sort(b+1,b+n+1,cmp1); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d %d",&q[i].k,&q[i].pp); q[i].id=i; } sort(q+1,q+m+1,cmp2); int now=0; for(int i=1;i<=m;i++){ while(now<q[i].k)Update(1,n,1,b[++now].pos); q[i].ans=Query(1,n,1,q[i].pp); } sort(q+1,q+m+1,cmp3); for(int i=1;i<=m;i++)printf("%d\n",q[i].ans); }
Optimal Subsequences(Hard Version)(二分套线段树+离线处理)
标签:div printf ret span air 处理 sub ref bsp
原文地址:https://www.cnblogs.com/Mmasker/p/11927495.html