Educational Codeforces Round 62 (Rated for Div. 2)

A. Detective Book

题意:一个人读书  给出每一章埋的坑在第几页可以填完 。 一个人一天如果不填完坑他就会一直看 问几天能把这本书看完

思路:模拟一下 取一下过程中最大的坑的页数  如果最大页数等于当前页数 day++即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define FOR(i,f_start,f_end) for(int i=f_start ;i<=f_end;i++)
 4 #define MT(x,i) memset(x,i,sizeof(x))
 5 #define inf 0x3f3f3f3f
 6 #define mkp make_pair
 7 #define all(v) (v).begin(),(v).end()
 8 #define F first
 9 #define S second
10 #define pii pair<int,int>
11 #define pb push_back
12 const int maxn=65000+5;
13 int a[maxn];
14 int main(){
15     int n,k;
16     scanf("%d",&n);
17     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
18     int p=1,maxnum=0;
19     int cnt=0;
20     while(p<=n){
21         if(a[p]>=maxnum){
22             maxnum=a[p];
23         }
24          if(p==maxnum){
25             cnt++;
26             maxnum=0;
27         }
28         p++;
29     }
30     cout<<cnt<<endl;
31     return 0;
32 }
View Code

B. Good String

题意:给出只含 >  <的字符串  >可以免费把右边的字符删掉  <可以免费把左边的字符删掉  越界就什么都没变化  问不免费删几次可以把该字符串全部变成一种字符

思路: 如果s[0]='>'或者s[n]='<'都是可以直接把一边全部免费删掉的   如果不是这两种情况 那么就找  从左边开始 和s[n] 相等  的最小位置   和从右边开始和s[1]相等的最小位置 哪个小输出哪个

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define FOR(i,f_start,f_end) for(int i=f_start ;i<=f_end;i++)
 4 #define MT(x,i) memset(x,i,sizeof(x))
 5 #define inf 0x3f3f3f3f
 6 #define mkp make_pair
 7 #define all(v) (v).begin(),(v).end()
 8 #define F first
 9 #define S second
10 #define pii pair<int,int>
11 #define pb push_back
12 const int maxn=65000+5;
13 char  s[maxn];
14 int main(){
15     int t;
16     int n;
17     scanf("%d",&t);
18     while(t--){
19         scanf("%d",&n);
20         scanf("%s",s+1);
21         if(s[1]!=s[n]){
22             if(s[1]=='<'){
23                 int ans=0;
24                 for(int i=n;i>=1;i--){
25                     if(s[i]=='<'){
26                         ans=n-i;break;
27                     }
28                 }
29                 for(int i=1;i<=n;i++){
30                     if(s[i]=='>'){
31                         ans=min(i-1,ans);
32                         break;
33                     }
34                 }
35                 cout<<ans<<endl;
36             }
37             else if(s[1]=='>'){
38                 cout<<0<<endl;
39             }
40 
41         }
42         else {
43             cout<<0<<endl;
44         }
45         
46                 
47     }
48     return 0;
49 }
View Code

C. Playlist

题意 给出n个pair 和k  可以选k个以内的Pair  问最大的  min(first)*(sigma(second))是多少

思路“:直接优先队列升序存second 然后按first 降序排列 n个pair 从最大的Pair开始枚举 每次进优先队列 如果队列超过k 就把 second小的出队即可 

比赛的时候想复杂了 想成了还要删除一个点  不知道怎么处理重复  其实删除也可以写 用multiset删除的时候只要删除find回的那个位置的值就不会把相同的全部删掉了

 1 #include<bits/stdc++.h>
 2 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
 3 #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
 4 #define F first 
 5 #define S second
 6 #define pii pair<long long  ,long long  >
 7 #define mkp make_pair
 8 #define pb push_back
 9 using namespace std;
10 typedef long long ll;
11 const int maxn=5e6+4;
12 priority_queue<int,vector<int>,greater<int> >q;
13 pii a[maxn];
14 bool  cmp(pii a,pii b){
15 return a.S>b.S;
16 }
17 int main(){
18     int n,k;
19     scanf("%d%d",&n,&k);
20     int x,y;
21     for(int i=1;i<=n;i++){
22         scanf("%d%d",&x,&y);
23        a[i].F=x;a[i].S=y;
24     }
25     sort(a+1,a+1+n,cmp);
26     q.push(a[1].F);
27     long long sum=a[1].F;
28     long long ans=1ll*a[1].F*a[1].S;
29     for(int i=2;i<=n;i++)
30     {
31         q.push({a[i].F});
32         sum+=a[i].F;
33         while(q.size()>k){sum-=q.top();q.pop();}
34         ans=max(ans,sum*a[i].S);
35     }
36     cout<<ans<<endl;
37 
38 
39     return 0;
40 }
View Code

D. Minimum Triangulation

题意:给出正n边形 分解成很多个不相交的三角形 并且不相交全覆盖正n边形  n边形角编号逆时针 1--n  三角形的权值为三个角编号乘积 问所有三角形最小乘积和是多少

思路:面向样例编程 每个三角形都从1点出发即可(不会证)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define FOR(i,f_start,f_end) for(int i=f_start ;i<=f_end;i++)
 4 #define MT(x,i) memset(x,i,sizeof(x))
 5 #define inf 0x3f3f3f3f
 6 #define mkp make_pair
 7 #define all(v) (v).begin(),(v).end()
 8 #define F first
 9 #define S second
10 #define pii pair<int,int>
11 #define pb push_back
12 const int maxn=65000+5;
13 char  s[maxn];
14 int main(){
15     int n,k;
16     scanf("%d",&n);
17     long long ans=0;
18     for(int i=2;i<=n-1;i++){
19         ans+=1ll*i*(i+1);
20     }
21     cout<<ans<<endl;
22 
23     return 0;
24 }
View Code

E. Palindrome-less Arrays

题意:给定一串数字  不确定的地方用-1 表示 确定的就有确切的数字  不能有大于1的奇回文串 问在-1的地方填数字  可以填1---k 有多少种填法

思路 :由不能有大于1的奇回文串 等价于 奇数序号的数字相邻不能相等 偶数序号的数字相邻不能相等 分解出来即可、

然后进行状态定义 dp[i][0/1]  表示i位置和下一个确定数字的数字相同的填法(第二维是1)  和不同的填法(第二维是0)

需要特殊处理开始和结尾 即 :- 1 -1 -1 -1 A      A表示已经确定的数字  开头的可能性为pow(k-1,有多少个1) 结尾类似

其余的确定数字之前的段可以提取出来分段dp 乘法原理乘起来即可

中间转移为 dp[i][1]=dp[i-1][0]

      dp[i][0]=dp[i-1][0]*(k-2)+dp[i-1][1]*(k-1) 

这里其实就是分类讨论的思想 如果dp只有一维的话那么后面的数字就会影响前面 产生后效性 

那么怎么取消这种后效性呢?那就是对后面的数字进行分类讨论 相当于已经确定了后面的数字 

所以前面填数字的时候就可以根据分类讨论的类别来进行转移 就可以取消后效性了

 1 #include<bits/stdc++.h>
 2 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
 3 #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
 4 #define F first 
 5 #define S second
 6 #define pii pair<long long  ,long long  >
 7 #define mkp make_pair
 8 #define pb push_back
 9 using namespace std;
10 typedef long long ll;
11 const int maxn=2e5+5;
12 const ll mod=998244353;
13 long long  a[maxn];
14 long long  dp[maxn][2];
15 ll n,k;
16 vector<ll>even,odd;
17 vector<ll>even_div,odd_div;
18 long long solve(const vector<ll>&a,const vector<ll>&div,int flag){
19     long long ans=1;
20     if(div.size()==0){
21         ans=k;
22         ans%=mod;
23         for(int i=1;i<a.size();i++){
24             ans*=(k-1);
25             ans%=mod;
26         }
27         return ans;
28     }
29     if(div[0]!=0){
30         for(int i=0;i<div[0];i++){
31             ans*=(k-1);
32             ans%=mod;
33         }
34     }
35     MS(dp,0);
36     for(int z=0;z<div.size()-1;z++){
37         //cout<<a[div[z]]<<" what ?  "<<a[div[z+1]]<<endl;
38         if(a[div[z]]!=a[div[z+1]]){
39             dp[div[z]][1]=0;
40             dp[div[z]][0]=1;
41         }
42         else dp[div[z]][1]=1,dp[div[z]][0]=0;
43     }
44     for(int z=1;z<div.size();z++){
45         //int zz=0;
46         if(a[div[z-1]]!=a[div[z]])dp[div[z-1]][0]=1;
47         for(int i=div[z-1]+1;i<div[z];i++){
48     //        zz=1;
49             //if(i!=div[z]-1)dp[i][0]=(((dp[i-1][1]+dp[i-1][0])%mod)*(k-1)%mod);
50              dp[i][0]=(((dp[i-1][0]*(k-2)%mod)+(dp[i-1][1]*(k-1)%mod))%mod);
51     //        cout<<i<<" ?? "<<dp[i-1][0]<<" fuck "<<dp[i-1][1]<<endl;
52             dp[i][1]=dp[i-1][0]%mod;
53             
54         }
55         ans=((ans*dp[div[z]-1][0])%mod);
56     }
57     for(int i=div[div.size()-1]+1;i<a.size();i++){
58         ans*=(k-1);
59         ans%=mod;
60     }
61     //cout<<ans<<endl;
62 return ans;    
63 }
64 int main(){
65     scanf("%lld%lld",&n,&k);
66     FOR(i,1,n)scanf("%lld",&a[i]);
67     for(int i=1;i<=n;i+=2){
68         odd.push_back(a[i]);    
69     }
70     for(int i=2;i<=n;i+=2){
71         even.push_back(a[i]);    
72     }
73     for(int i=0;i<odd.size();i++){
74         if(odd[i]!=-1)odd_div.push_back(i);
75         if(i!=0&&odd[i]==odd[i-1]&&odd[i]!=-1){
76         cout<<0<<endl;
77             return 0;
78         }
79         
80     }
81     for(int i=0;i<even.size();i++){
82         if(i!=0&&even[i]==even[i-1]&&even[i]!=-1){
83             cout<<0<<endl;
84             return 0;
85         }
86         if(even[i]!=-1)even_div.push_back(i);
87     }
88     long long temp1,temp2;
89     temp1=solve(odd,odd_div,1);
90     temp2=solve(even,even_div,0);
91     cout<<((temp1%mod)*(temp2%mod))%mod<<endl;
92     return 0;
93 }
View Code
原文地址:https://www.cnblogs.com/ttttttttrx/p/10591456.html