(color{Red}题目大意)
(给出一个长n序列,要求每次选出一个长k的子序列,使得)
(子序列的元素和最大且字典序最小,问第pos个元素是多少.)
(color{orange}对于easy版本,我们可以很暴力的写)
(直接把元素按照大小关系存进vector)
(每次选取最大的元素,如果有多个就选最前面的那个)
(你可能有疑问,为什么最大的元素选最前面的呢?)
(当取完这种元素时,对答案没有影响,都要选)
(如果没取完这种元素,那么这种元素是所取的最小元素,肯定选最前面的)
(元素确定了,按照先后顺序排个序,就好了)
#include <bits/stdc++.h>
using namespace std;
const int maxn=209;
int n,top,k,t,pos,tot;
struct p{
int x,num;
}a[209],b[209];
bool big(p a,p b){
return a.x<b.x;
}
bool zi(p a,p b){
return a.num<b.num;
}
vector<p>vec[maxn];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>a[i].x;
a[i].num=i;
}
sort(a+1,a+1+n,big);
vec[++top].push_back(a[1]);
for(int i=2;i<=n;i++)
{
if(a[i].x==a[i-1].x) vec[top].push_back(a[i]);
else vec[++top].push_back(a[i]);
}
for(int i=1;i<=top;i++) sort(vec[i].begin(),vec[i].end(),zi);
cin>>t;
while(t--)
{
cin>>k>>pos;
tot=0;
int w=0;
for(int i=top;i>=1;i--)
{
for(int j=0;j<vec[i].size();j++)
{
b[++w]=vec[i][j];
if(w==k) break;
}
if(w==0) break;
}
sort(b+1,b+1+k,zi);
cout<<b[pos].x<<endl;
}
}
(color{Red}hard难度)
(按照上面的的easy版本,对于每个k要取的数是固定的)
(而且长度为k的序列只比k-1的最大序列多了一个数而已)
(于是我们离线操作,把所有询问存起来,按照k小到大排序)
(先处理k最小的,选出最大的k个元素,放在树状数组上标记使用过)
(然后我们就二分出哪个点刚好使用了pos个数字,就是答案)
(color{green}非常巧妙)
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+9;
int n,b[maxn],m,ans[maxn];
struct p{
int x,num;
bool operator < (const p&tmp ) const{
return this->x==tmp.x?this->num<tmp.num:this->x>tmp.x;
}
}a[maxn];
struct quest{
int k,pos,index;
bool operator < (const quest &tmp) const{
return this->k<tmp.k;
}
}q[maxn];
class binary_tree
{
private:
int sumn[maxn];
int lowbit(int x){return x&(-x);}
public:
void update(int x,int k){
while(x<=n) sumn[x]+=k,x+=lowbit(x);
}
int ask(int x){
int ans=0;
while(x) ans+=sumn[x],x-=lowbit(x);
return ans;
}
}tree;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].x;
a[i].num=i;
b[i]=a[i].x;
}
sort(a+1,a+1+n);
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>q[i].k>>q[i].pos;
q[i].index=i;
}
sort(q+1,q+1+m);
int cur=1;
for(int i=1;i<=m;i++)
{
for(;cur<=q[i].k;cur++) tree.update(a[cur].num,1);
int l=1,r=n;
while(r>l)
{
int mid=l+r>>1;
if(tree.ask(mid)>=q[i].pos) r=mid;
else l=mid+1;
}
ans[q[i].index]=b[r];
}
for(int i=1;i<=m;i++) cout<<ans[i]<<endl;
}
int main()
{
solve();
}