AcWing周赛 1

A:水题。

  给定两个数组,找到从这俩数组中各找一数,使得和不在任何一个数组中。

  因为数组中的数都是正整数,最大的俩数相加必然不在这俩数组之中。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 110;
 6 int a[N],b[N];
 7 int main()
 8 {
 9     int n,m;
10     cin>>n;
11     for(int i=0;i<n;i++)
12         cin>>a[i];
13     cin>>m;
14     for(int j=0;j<m;j++)
15         cin>>b[j];
16     sort(a,a+n);
17     sort(b,b+m);
18     cout<<a[n-1]<<" "<<b[m-1]<<endl;
19     return 0;
20 }

 

 

 

B:给定一个数组和一个操作次数,每次操作将某一个数加一,问中位数最大为多少。

可以发现只和排序数组的后半部分有关。

解法1:二分,时间复杂度为nlog(n)。

可以观察到随着操作次数的增加,中位数的数值单调增加。

故二分中位数的数值,通过操作次数与k进行比较进行判断。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const LL N=2e5+10;
 7 LL w[N];
 8 LL n,k;
 9 bool check(int mid){
10     LL res=0;
11     for(int i=n/2;i<n;i++){
12         if(w[i]<mid)
13             res+=mid-w[i];
14     }
15     return res<=k;
16 }
17 int main()
18 {
19     cin>>n>>k;
20     for(int i=0;i<n;i++) cin>>w[i];
21     sort(w,w+n);
22     LL l=0,r=2e9;
23     while(l<r){
24         LL mid=l+r+1>>1;
25         if(check(mid)) l=mid;
26         else r=mid-1;
27     }
28     cout<<r;
29     return 0;
30 }

 

解法2:模拟,时间复杂度nlog(n)。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 const LL N=2e5+10;
 7 LL a[N],q[N];
 8 LL n,k;
 9 int main()
10 {
11     cin>>n>>k;
12     for(int i=1;i<=n;i++){
13         cin>>a[i];
14     }
15     sort(a+1,a+1+n);
16     LL pos=(n+1)/2;
17     for(int i=pos+1;i<=n;i++){
18         q[i]=(a[i]-a[i-1])*(i-pos);//计算出若将pos~i变为a[i]需要再加多少次操作【注意再字】
19     }
20     int res=-1;
21     int i;
22     for(i=pos;i<=n&&k>=q[i];i++){
23         k-=q[i];
24     }
25     i--;//-1之后是符合条件的
26     cout<<a[i]+k/(i-pos+1);
27     return 0;
28 }

 

 

 

C:最开始的含有n个元素的数组的序列为1~n,给定一个大小为n的移动数组,假设为5,1,2,4,3,问每个数经过多少次操作能够回来。

比如1,第一次操作到5

     第二次操作到3

     第三次操作到2

     第四次操作到1

将移动数组抽象为图的话。

 

答案为环的大小。[4,4,4,1,4]

分析到这一步,就可以直接建图,然后tarjan了(我不会)。

 

又因为每一个点的出度为1,入度也为1,所以每一个环必然是一个连通块,所以本题也可以用并查集来写。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 2e5+10;
 6 int p[N],c[N];
 7 int find(int x){
 8     if(p[x]!=x)
 9         p[x]=find(p[x]);
10     return p[x];
11 }
12 int main()
13 {
14     int T;
15     cin>>T;
16     while(T--){
17         int n;
18         cin>>n;
19         for(int i=1;i<=n;i++) p[i]=i,c[i]=1;
20         for(int i=1;i<=n;i++){
21             int x;
22             cin>>x;
23             int fa=find(i);
24             int fb=find(x);
25             p[fa]=fb;
26             if(fa!=fb)
27                 c[fb]+=c[fa];
28         }
29         for(int i=1;i<=n;i++)
30             cout<<c[find(i)]<<" ";
31         cout<<endl;
32     }
33     return 0;
34 }

 

posted on 2021-06-01 13:59  greenofyu  阅读(44)  评论(0编辑  收藏  举报