A
题意:
给你一串递增数列,找出不能构成三角形的三个数,否则输出$-1$。
分析:
签到题,一开始没看到是递增的,还用$pair$排了个序(活该)。直接判断最小的两个和最大的关系,如果这个可以那么全部都可以。
1 #include2 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 17 }else{ 18 cout<<-1<<endl; 19 } 20 } 21 return 0; 22 }>a[i]; 15 if(a[0]+a[1]<=a[n-1]){ 16 cout<<1<<' '<<2<<' '< endl;
B
题意:
给你一串$01$列,每次可以拿走连续的数字,得到的分数就是拿走的$1$的个数。两个选手都最优选择,问先手能拿多少分。
分析:
把原来的字符串处理一下,连续的$1$都加起来,把$0$删掉,可以知道如果有连续的那必然先拿最长的,而且后手也是那当前最长的。所以给这些数字排序,反转,取偶数位即可。
1 #include2 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 27 if(i%2==0) al+=b[i]; 28 } 29 cout<){ 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 #include2 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 0'-1; 16 sum[0]=a[0];//cout<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 ' 17 for(int i=1;i ]+a[i];//cout<1 18 ll res=0,ze=0; 19 for(int i=0;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<){ 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 #include2 #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< 40 return 0; 41 }endl;