2022/7/17 每日一题(构造+数学+贪心+指针)
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022/7/17 每日一题(构造+数学+贪心+指针)相关的知识,希望对你有一定的参考价值。
D. Permutation Restoration
题意:数组a(由1~n组成)通过计算格式i/a[i]
转化为数组b,现在给定数组b,要求还原出数组a,输出其中一种可能即可。
思路:
1.i/a[i]=b[i]
可通过数学思维转化为 a[i]*b[i]=<i<a[i]*(b[i]+1)
进一步转化为 i/(b[i]+1)<a[i]<=i/b[i]
,最终为 i/(b[i]+1)+1=<a[i]<=i/b[i]
2.由此确定了每一个a[i]的取值范围,下一步确定1~n中每一个值的归属。
3.对每个a[i]的范围进行排序,根据左范围l进行从小到大排序;若相等,则再根据右范围升序排列。
4.创建一个pair类型的优先队列,第一关键字为右范围,第二关键字为b[i]中编号。
(pair默认是先对第一个关键字从小到大排序,如果第一关键字相同,在对第二关键字从小到大排序,都是升序)
5.非常关键的特判,如果b[i]为0,那么a[i]范围应该是[i+1,n]
.要特别得区别于数学公式推出来的范围。
代码:
#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
#define pii pair<int,int>
using namespace std;
const int N=1e6+6;
struct node
int l,r,id;
e[N];
int n,a[N],b[N];
bool cmp(node n1,node n2)
if(n1.l==n2.l)
return n1.r<n2.r;
return n1.l<n2.l;
signed main()
int t;cin>>t;
while(t--)
cin>>n;
for(int i=1;i<=n;i++)
cin>>b[i];
e[i].id=i;
e[i].l=i/(b[i]+1)+1;
if(b[i]==0)
e[i].r=n;
else
e[i].r=i/b[i];
sort(e+1,e+n+1,cmp);
priority_queue<pii,vector<pii>,greater<pii> >q;
int k=1;
for(int i=1;i<=n;i++)
while(k<=n&&e[k].l<=i)
q.push(e[k].r,e[k].id);
k++;
int g=q.top().second;
q.pop();
a[g]=i;
for(int i=1;i<=n;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
以上是关于2022/7/17 每日一题(构造+数学+贪心+指针)的主要内容,如果未能解决你的问题,请参考以下文章