Educational Codeforces Round 64 (Rated for Div. 2)

文章目录

  • A. Inscribed Figures(思维)
  • B. Ugly Pairs(贪心 + 构造)
  • C. Match Points(二分 + 贪心)
  • E. Special Segments of Permutation(思维 + set)


A. Inscribed Figures(思维)

原题链接:http://codeforces.com/contest/1156/problem/A


题意: 给出 n 个图形(1 代表圆,2 代表高等于底的等腰三角形,3 代表矩形,相邻图形不会相等),从左到右,右边的内嵌在左边的图形里面,要求尽量最大而且各种平行的放,求图形中想接触的点的个数.

思路: 总共有六种情况,分别是12,13,21,23,31,32,把这两种情况都列出来,然后特判 312 这种情况,会有一个点重叠,要减掉。


Code(C++):

#include 
using namespace std;
int a[105];
int main(){
    int n;  cin>>n;
    cin>>a[1];
    int ans=0;
    for(int i=2;i<=n;i++){
        cin>>a[i];
        if(a[i]==3 && a[i-1]==2){
            cout<<"Infinite"<<endl;
            return 0;
        }
        if(a[i]==2 && a[i-1]==3){
            cout<<"Infinite"<<endl;
            return 0;
        }
        if(a[i]==1 && a[i-1]==2)
            ans+=3;
        if(a[i]==3 && a[i-1]==1)
            ans+=4;
        if(a[i]==2 && a[i-1]==1)
            ans+=3;
        if(a[i]==1 && a[i-1]==3)
            ans+=4;
    }
    for(int i=3;i<=n;i++){
        if(a[i]==2&&a[i-1]==1&&a[i-2]==3)
            ans--;
    }
    cout<<"Finite"<<endl;
    cout<<ans<<endl;
    return 0;
}


B. Ugly Pairs(贪心 + 构造)

原题链接: http://codeforces.com/contest/1156/problem/B


题意: 给你一个字符串,将他们重新排列,使得相邻的字符在字母表中不是相邻的。

思路: 先将字符串从小到大排个序,奇数位的字符存入s1字符串,偶数位的字符存入s2字符串,他们内部相邻的字符在字母表中一定不是相邻的。然后有两种情况,s1 + s2 和 s2 + s1,判断两个字符串的相接处在字母表中是否为相邻的。


Code(C++):

#include 
#include 
#include 
#include 
using namespace std;
int main(){
    int t;  cin>>t;
    while(t--){
        string str;
        cin>>str;
        sort(str.begin(),str.end());
        string s1,s2;
        for(int i=0;i<str.size();i++){
            if((str[i]-'a')%2)  s1+=str[i];
            else    s2+=str[i];
        }
     //编译器不能用字符串的back()函数和front()函数,但提交能过
     /*   if(abs(s2.front()-s1.back())>1)
            cout<1)
            cout<
        int len1=s1.size(),len2=s2.size();
        if(abs(s2[0]-s1[len1-1])>1)
            cout<<s1+s2<<endl;
        else if(abs(s1[0]-s2[len2-1])>1)
            cout<<s2+s1<<endl;
        else
            cout<<"No answer"<<endl;
    }
    return 0;
}


C. Match Points(二分 + 贪心)

原题链接: http://codeforces.com/contest/1156/problem/C


题意: 有 n 个数,问有多少对 ai,aj 能使得 |ai-aj|>=z ,同时 ai 和 aj 只能用一次。

思路: 因为最多有 n/2 对,所以先对数组从小到大排序,然后分成两组,用前面 n/2 个数与后面 n/2 个数比较,得出的结果即为最大值。


Code(C++):

#include 
#include 
#include 
using namespace std;
const int N=2e5+10;
int a[N],vis[N];
int main(){
    int n,z;
    cin>>n>>z;
    for(int i=0;i<n;i++)
        cin>>a[i];
    sort(a,a+n);
    int ans=0,l=0,r;
    if(n%2) r=n/2+1;
    else    r=n/2;
    while(l<r){
        if(a[r]-a[l]>=z){
            ans++;
            l++;
        }
        r++;
        if(r==n)    break;
    }
    cout<<ans<<endl;
    return 0;
}


E. Special Segments of Permutation(思维 + set)

原题链接: http://codeforces.com/contest/1156/problem/E


题意: 给一个1 ~ n的排列,求出有多少个区间满足a[l] + a[r] = max(a[l] ~ a[r])。

思路: 枚举最大值,然后对于每个最大值,把其左边暂时符合条件的区间左端点存入 set 集合里,然后枚举该最大值右边符合条件的数,如果集合里存在该最大值减去该值的差,则答案加1。


Code(C++):

#include 
#include 
using namespace std;
const int N=2e5+10;
int a[N];
int main(){
    int n;  cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    int ans=0;
    for(int i=2;i<n;i++){
        //先寻找到最大值
        if(a[i]<a[i-1] || a[i]<a[i+1])  continue;
        set<int> s;
        for(int j=i-1;j>=1&&a[j]<a[i];j--)  //寻找区间左端点
            s.insert(a[j]);
        for(int j=i+1;j<=n&&a[j]<a[i];j++){ //寻找区间右端点
            if(s.count(a[i]-a[j]))  //判断集合里是否存在符合条件的数
                ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}


你可能感兴趣的:(Educational Codeforces Round 64 (Rated for Div. 2))