随笔 - 58,  文章 - 0,  评论 - 4,  阅读 - 3296

一、题目描述:

  给你一个长度为 n 的序列 a , 你需要进行 q 次操作。

     x  v 

  每次操作后,输出序列前 k 大的元素和

  数据范围:1n,q5×105, 109val109


 二、解题思路:

  用两个 set 维护,s1 维护前 k 大,s2 维护非前 k 大 。

  每次将 s2  中最大的与 s1 中最小的进行比较,若能更大就交换。

  好奇妙的思路啊!不愧是 jiangly ! orz 。时间复杂度 O(nlog2n)


 三、完整代码:

复制代码
 1 #include<iostream>
 2 #include<set>
 3 #define N 500010
 4 #define ll long long
 5 using namespace std;
 6 multiset <ll> s1,s2;
 7 ll n,k,q,x,y,ans,a[N];
 8 int main()
 9 {
10     ios::sync_with_stdio(false);
11     cin.tie(0);cout.tie(0);
12     cin>>n>>k>>q;
13     for(ll i=1;i<=n;i++)
14         if(i<=k)    s1.insert(a[i]);
15         else        s2.insert(a[i]);
16     for(ll i=1;i<=q;i++)
17     {
18         cin>>x>>y;
19         ll t=y-a[x];
20         if(k==n)
21         {
22             a[x]=y;ans+=t;
23             cout<<ans<<'\n';
24             continue;
25         }
26         auto iter1=s1.find(a[x]);
27         auto iter2=s2.find(a[x]);
28         if(iter1!=s1.end())
29             s1.erase(iter1),s1.insert(y),ans+=t;
30         else    s2.erase(iter2),s2.insert(y);
31         a[x]=y;iter1=s1.begin();
32         iter2=s2.end(); iter2--;
33         x=*iter1,y=*iter2,t=y-x;
34         while(t>0)
35         {
36             ans+=t;
37             s1.erase(iter1),s1.insert(y);
38             s2.erase(iter2),s2.insert(x);
39             iter1=s1.begin();
40             iter2=s2.end();iter2--;
41             x=*iter1,y=*iter2,t=y-x;
42         }
43         cout<<ans<<'\n';
44     }
45     return 0;
46 }
复制代码

四、写题心得:

  set中位置的访问相对繁琐,但也不是很难。收获经验如下:

  1set =>Exp++!

  2访 set  auto iter=s.end(),iter =>Exp++

 

posted on   trh0630  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示