「杂题乱刷2」CF1227D2
题目链接
CF1227D1 Optimal Subsequences (Hard Version) *1600
CF1227D2 Optimal Subsequences (Hard Version) *1800
解题思路
本篇题解分 D1,D2 两个部分来写。
D1 sol:
我们容易发现有以下两点性质:
-
要想子序列和最大,必须选择前 \(k\) 大的数字。
-
比第 \(k\) 大的数字还要大的数字是必须取的。
然后容易发现,我们能改变序列的差异只能是改变所有值为第 \(k\) 大的数的选取情况。
那么显然,选取最前面的数是最优的。
直接暴力选取即可,时间复杂度 \(O(nm + n \log n)\)。
D2 sol:
根据 D1 的思路,我们需要优化掉这个暴力。
考虑将询问离线,并按照查询的序列长度从小到大进行排序。
这样我们就只需要维护加数操作和目前加的数字有几个值为第 \(k\) 大的数字即可。
加数操作和查询操作我们可以使用优先队列和树状数组维护。
时间复杂度 \(O(m \log^2 n)\)。
参考代码
D1 code:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define pii pair<ll,ll>
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) (1ll*(x)/__gcd(x,y)*(y))
#define Sum(x,y) (1ll*((x)+(y))*((y)-(x)+1)/2)
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<ll>
#define minqueue priority_queue<ll,vector<ll>,greater<ll>>
#define bug cout<<"---------------------------------------\n";
ll _t_;
void _clear(){}
ll n,q;
ll a[100010],b[100010];
ll k;
map<ll,ll>mp,mp2;
bool cmp(ll x,ll y){
return x>y;
}
void solve()
{
_clear();
cin>>n;
forl(i,1,n)
cin>>a[i],mp[a[i]]=1;
for(auto i:mp)
mp2[i.x]=++k;
for(auto i:mp2)
mp[i.y]=i.x;
forl(i,1,n)
a[i]=mp2[a[i]],b[i]=a[i];
sort(b+1,b+1+n,cmp);
cin>>q;
while(q--)
{
ll x,y;
cin>>x>>y;
ll sum=0,num=b[x];
ll last=0,L=x;
while(b[L]==num)
L--,last++;
forl(i,1,n)
{
sum+=a[i]>num;
if(a[i]==num && last)
last--,sum++;
if(sum==y)
{
cout<<mp[a[i]]<<endl;
break;
}
}
}
}
int main()
{
// freopen("tst.txt","r",stdin);
// freopen("sans.txt","w",stdout);
IOS;
_t_=1;
// cin>>_t_;
while(_t_--)
solve();
QwQ;
}
D2 code:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll i=a;i<=b;i++)
#define forr(i,a,b) for(re ll i=a;i>=b;i--)
#define forll(i,a,b,c) for(re ll i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(re ll i=a;i>=b;i-=c)
#define pii pair<ll,ll>
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
#define db long double
#define ull unsigned long long
#define lcm(x,y) (1ll*(x)/__gcd(x,y)*(y))
#define Sum(x,y) (1ll*((x)+(y))*((y)-(x)+1)/2)
#define x first
#define y second
#define aty cout<<"Yes\n";
#define atn cout<<"No\n";
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
#define xxy cout<<"yes\n";
#define xxn cout<<"no\n";
#define printcf(x) x?cout<<"YES\n":cout<<"NO\n";
#define printat(x) x?cout<<"Yes\n":cout<<"No\n";
#define printxx(x) x?cout<<"yes\n":cout<<"no\n";
#define maxqueue priority_queue<pii>
#define minqueue priority_queue<pii,vector<pii>,greater<pii>>
#define bug cout<<"---------------------------------------\n";
template<typename T1,typename T2>bool Max(T1&x,T2 y){if(y>x)return x=y,1;return 0;}
template<typename T1,typename T2>bool Min(T1&x,T2 y){if(y<x)return x=y,1;return 0;}
ll _t_;
void _clear(){}
ll n,Q;
ll a[1000010],b[1000010];
ll k;
map<ll,ll>mp,mp2;
bool cmp(ll x,ll y){
return x>y;
}
struct node{
ll x,y,id;
}q[1000010];
bool pmc(node x,node y){
return x.x<y.x;
}
maxqueue qu;
ll ans[1000010];
ll tree[1000010];
ll qwq[1000010];
void add(ll x,ll y){
for(;x<=2e5+5;x+=lowbit(x))
tree[x]+=y;
}
ll query(ll x)
{
ll sum=0;
for(;x;x-=lowbit(x))
sum+=tree[x];
return sum;
}
void solve()
{
_clear();
cin>>n;
forl(i,1,n)
cin>>a[i],mp[a[i]]=1;
for(auto i:mp)
mp2[i.x]=++k;
for(auto i:mp2)
mp[i.y]=i.x;
forl(i,1,n)
a[i]=mp2[a[i]],b[i]=a[i];
sort(b+1,b+1+n,cmp);
forl(i,1,n)
qu.push({a[i],-i});
cin>>Q;
forl(i,1,Q)
cin>>q[i].x>>q[i].y,q[i].id=i;
sort(q+1,q+1+Q,pmc);
ll sz=0;
forl(i,1,Q)
{
while(sz<q[i].x)
{
pii now=qu.top();
qu.pop();
add(-now.y,1);
// add(-now.y+1,-1);
sz++;
}
ll L=1,R=n;
while(L<R)
{
ll Mid=(L+R)/2;
if(query(Mid)<q[i].y)
L=Mid+1;
else
R=Mid;
}
ans[q[i].id]=mp[a[L]];
qwq[q[i].id]=L;
}
forl(i,1,Q)
// cout<<qwq[i]<<':',
cout<<ans[i]<<endl;
}
int main()
{
// freopen("tst.txt","r",stdin);
// freopen("sans.txt","w",stdout);
IOS;
_t_=1;
// cin>>_t_;
while(_t_--)
solve();
QwQ;
}