Test 2020/9/05
阿新 • • 發佈:2020-10-07
https://www.qizhishu.com/codeadmin/front/client/myCplusplusCompetitionDetail.zhtml?ID=675
pj難度的一場模擬賽,得分300/400.
完美夏冰
簽到題。
#include<bits/stdc++.h> using namespace std; int a[4]; int main() { cin>>a[0]>>a[1]>>a[2]>>a[3]; sort(a,a+4); puts(a[0]+a[3]==a[1]+a[2]?"Perfect":"Biu"); return 0; }
瘋狂秋風
看到k的範圍這麼小,就要把時間複雜度往k上靠。
把資料從小到大排序之後觀察到,兩個數排名都大於k的二元組(如a[k+1]+a[k+2])是不可能排到第k小的。於是雙重迴圈只需要跑到k即可。時間複雜度\(O(k^2)\)。
#include<bits/stdc++.h> using namespace std; int a[100010]; priority_queue<int,vector<int>,greater<int> > q; int main() { int n,k; cin>>n>>k; for(int i=1;i<=n;i++) scanf("%d",&a[i]); sort(a+1,a+1+n); for(int i=1;i<=min(k,n);i++) for(int j=1;j<=min(k,n);j++) q.push(a[i]+a[j]); for(int i=1;i<k;i++) q.pop(); printf("%d\n",q.top()); return 0; }
極端寒冬
暫未想到合適解法。
風吹櫻花
大致題意:
給定長度為\(n\)的序列\(A\)與一個數\(k\),要求構造一個\(x\)序列滿足\(x_1+x_2+..x_n=k\)並且\(a_1*(x_1)^2+a_2*(x_2)^2...a_n*(x_n)^2\)最小,輸出這個最小值。
首先想到把序列A從小到大排序,那麼對應的x應該是不上升的。
那麼最簡單的一個不上升的序列就是把k全部疊到\(x_1\)上。初始的ans的值就是\(a_1*k^2\)
然後可知\(a^2-(a-1)^2=2a-1,(a+1)^2-a^2=2a+1\)。
所以我們要把\(x_1\)上的一部分k分到其他a身上。如果從\(x_1\)
ans-=(a_1*(2*x_1-1)-a_i*(2*x_i+1))
。
不僅如此,還要貪心地選擇增加的權值最小的那個\(a_i*(2*x_i+1)\),這樣能讓操作最優化。
於是大致思路就是每次找到一個最小的\(a_i*(2*x_i+1)\),如果它小於第一項減少的權值,那麼就進行操作並繼續下去,否則說明繼續操作不能更優了,返回。
這一步操作用優先佇列優化降到log級別即可通過。
總時間複雜度\(O(klogn)\)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int x[100010];
int a[100010];
struct node
{
int val,id;
bool operator < (const node &a) const
{
return a.val<val;
}
};
priority_queue<node> q;
signed main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
sort(a+1,a+1+n);
int ans=a[1]*k*k,flag=1;
if(n==1)
{
printf("%lld\n",ans);
return 0;
}
x[1]=k;
for(int i=2;i<=n;i++)
q.push((node){a[i]*(2*x[i]+1),i});
int fst=a[1]*(2*x[1]-1);
while(fst>q.top().val)
{
node tmp=q.top();
q.pop();
ans-=(fst-tmp.val);
x[tmp.id]++;
q.push((node){a[tmp.id]*(2*x[tmp.id]+1),tmp.id});
x[1]--;
fst=a[1]*(2*x[1]-1);
}
printf("%lld\n",ans);
return 0;
}