Educational Codeforces Round 93 (Rated for Div. 2)

A

题意:

给你一串递增数列,找出不能构成三角形的三个数,否则输出$-1$。

分析:

签到题,一开始没看到是递增的,还用$pair$排了个序(活该)。直接判断最小的两个和最大的关系,如果这个可以那么全部都可以。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll maxn=1e5+100;
 5 const ll mod=1e9+7;
 6 const ll inf=0x3f3f3f3f3f3f3f3f;
 7 ll t,n;
 8 ll a[maxn];
 9 int main(){
10     //freopen("in.txt","r",stdin);
11     cin>>t;
12     while(t--){
13         cin>>n;
14         for(int i=0;i<n;i++)cin>>a[i];
15         if(a[0]+a[1]<=a[n-1]){
16             cout<<1<<' '<<2<<' '<<n<<endl;
17         }else{
18             cout<<-1<<endl;
19         }
20     }
21     return 0;
22 }

B

题意:

 给你一串$01$列,每次可以拿走连续的数字,得到的分数就是拿走的$1$的个数。两个选手都最优选择,问先手能拿多少分。

分析:

 把原来的字符串处理一下,连续的$1$都加起来,把$0$删掉,可以知道如果有连续的那必然先拿最长的,而且后手也是那当前最长的。所以给这些数字排序,反转,取偶数位即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll maxn=1e5+100;
 5 const ll mod=1e9+7;
 6 const ll inf=0x3f3f3f3f3f3f3f3f;
 7 ll t,n,b[maxn];
 8 string a;
 9 int main(){
10     //freopen("in.txt","r",stdin);
11     cin>>t;
12     while(t--){
13         cin>>a;
14         ll cnt=0;
15         for(int i=0;i<a.size();){
16             if(a[i]=='0'){
17                 while(a[i]=='0')i++;
18             }else{
19                 ll cn=0;
20                 while(a[i]=='1')cn++,i++;
21                 b[cnt++]=cn;
22             }
23         }
24         sort(b,b+cnt);reverse(b,b+cnt);
25         ll al=0;
26         for(int i=0;i<cnt;i++){
27             if(i%2==0) al+=b[i];
28         }
29         cout<<al<<endl;
30     }
31     return 0;
32 }

C

题意:

 给你一串数列$a_i$,问有多少个$i \le j$满足$\sum_{k=i}^j{a_k}=j-i+1$。

分析:

 变形一下,得到$\sum_{k=i}^j{(a_k-1)}=0$。那就很显然了,前缀和,然后找到区间和为$0$的个数,那么这个$sum[i]$和$sum[j]$只能是相等或者本身为$0$。造一个新的数列,然后$map$记录元素出现次数,然后一加就行,$0$要额外加本身。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll maxn=1e5+100;
 5 const ll mod=1e9+7;
 6 const ll inf=0x3f3f3f3f3f3f3f3f;
 7 ll t,n,a[maxn],sum[maxn];
 8 string s;
 9 map<ll,ll> mp;
10 int main(){
11     //freopen("in.txt","r",stdin);
12     cin>>t;
13     while(t--){
14         cin>>n>>s;
15         for(int i=0;i<n;i++)a[i]=s[i]-'0'-1;
16         sum[0]=a[0];//cout<<sum[0]<<' ';
17         for(int i=1;i<n;i++) sum[i]=sum[i-1]+a[i];//cout<<sum[i]<<' ';cout<<endl;
18         ll res=0,ze=0;
19         for(int i=0;i<n;i++){
20             mp[sum[i]]++;
21         }
22         for(auto i:mp){
23             ll te=i.second;
24             if(i.first==0){
25                 res+=te+te*(te-1)/2;
26             }else{
27                 if(te>1){
28                     res+=te*(te-1)/2;
29                 }
30             }
31         }cout<<res<<endl;
32         mp.clear();
33     }
34     return 0;
35 }

D

题意:

 给你三种颜色的木棒,每次选择两个颜色不一样的变成矩形并获得面积,问最大获得多少面积。

分析:

 没做出来,用堆或者,放在一个大数组里面都不行,明天看看题解吧。其实我一开始就知道是$dp$,奈何写不出来,看了眼别人的提交以后恍然大悟。

用一个三维的数组$dp[i][j][k]$,表示已经取了$r,g,b$三种木棒的前$i,j,k$大的木棒。那么状态转移方程就是:

$$
dp\left[ i \right] \left[ j \right] \left[ k \right] =\max \left( \begin{array}{c}
dp\left[ i-1 \right] \left[ j-1 \right] \left[ k \right] +r\left[ i \right] g\left[ j \right]\\
dp\left[ i \right] \left[ j-1 \right] \left[ k-1 \right] +g\left[ j \right] b\left[ k \right]\\
dp\left[ i-1 \right] \left[ j \right] \left[ k-1 \right] +r\left[ i \right] b\left[ k \right]\\
\end{array} \right)
$$

对于初始条件,$dp[0][0][0]=0$,其他的均赋值为$-1$,然后三重循环就可以了。

 1 #include<bits/stdc++.h>
 2 #define rep(i,a,b) for(ll i=(a);i<=(b);i++)
 3 #define per(i,a,b) for(ll i=(a);i>=(b);i--)
 4 using namespace std;
 5 typedef long long ll;
 6 const ll maxn=1e5+100;
 7 const ll mod=1e9+7;
 8 const ll inf=0x3f3f3f3f3f3f3f3f;
 9 ll t,r[1000],g[1000],b[1000],num[5];
10 ll dp[205][205][205];
11 int main(){
12     //freopen("in.txt","r",stdin);
13     rep(i,1,3) cin>>num[i];
14     rep(i,1,num[1]) cin>>r[i];
15     rep(i,1,num[2]) cin>>g[i];
16     rep(i,1,num[3]) cin>>b[i];
17     sort(r+1,r+num[1]+1),reverse(r+1,r+num[1]+1);
18     sort(g+1,g+num[2]+1),reverse(g+1,g+num[2]+1);
19     sort(b+1,b+num[3]+1),reverse(b+1,b+num[3]+1);
20     memset(dp,-1,sizeof(dp));
21     dp[0][0][0]=0;
22     ll res=0;
23     rep(i,0,num[1]){
24         rep(j,0,num[2]){
25             rep(k,0,num[3]){
26                 if(i>0&&j>0&&dp[i-1][j-1][k]>=0){
27                     dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+r[i]*g[j]);
28                 }
29                 if(k>0&&j>0&&dp[i][j-1][k-1]>=0){
30                     dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-1]+b[k]*g[j]);
31                 }
32                 if(i>0&&k>0&&dp[i-1][j][k-1]>=0){
33                     dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]+r[i]*b[k]);
34                 }
35                 res=max(res,dp[i][j][k]);
36             }
37         }
38     }
39     cout<<res<<endl;
40     return 0;
41 }

 

 

 

posted @ 2020-08-15 00:40  Zabreture  阅读(296)  评论(0编辑  收藏  举报