20180715练习赛 [CF]EDU ROUND 4

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CQBZLYTina/article/details/81976418

A - The Text Splitting CodeForces - 612A
B - HDD is Outdated Technology CodeForces - 612B
C - Replace To Make Regular Bracket Sequence CodeForces - 612C
D - The Union of k-Segments CodeForces - 612D

A

水题 直接过
给你一个字符串,让你分割成长度为p,或者长度为q的串 问你如何分割

#include<cstdio>
#define MAXN 100
int N,p,q;
char s[MAXN+10];
int main()
{
    scanf("%d %d %d",&N,&p,&q);
    scanf("%s",s+1);
    for(int i=0;i<=MAXN;i++)
        for(int j=0;j<=MAXN;j++)
            if(i*p+j*q==N)
            {
                printf("%d\n",i+j);
                int now=1;
                for(int k=1;k<=i;k++)
                {
                    for(int l=1;l<=p;l++)
                        printf("%c",s[now++]);
                    puts("");
                }
                for(int k=1;k<=j;k++)
                {
                    for(int l=1;l<=q;l++)
                        printf("%c",s[now++]);
                    puts("");
                }
                return 0;
            }
    printf("-1\n");
    return 0;
}

B

给出一组n的全排列的一组数(1~N,只是数字顺序乱了),求按从小到大,它们之间间隔位置的总和
也很水 注意n比较大 不能直接枚
记录每个数的位置,然后一个循环依次计算
注意要开long long

#include<cstdio>
#include<cstdlib>
using namespace std;
#define MAXN 200008
int N;
long long ans;
int a[MAXN],b[MAXN];
int main()
{
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
    {
        scanf("%d",&a[i]);
        b[a[i]]=i;
    }
    for(int i=2;i<=N;i++)
        ans+=abs(b[i]-b[i-1]);
    printf("%lld\n",ans);
    return 0;
}
//long long 不开毁前程

C

经典的括号匹配问题 但是考场上忘了 自己搞了很久 最后搞了个数组模拟栈

#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 1000005
char s[MAXN],l[MAXN];
int cnt[10],ans;
int main()
{
    scanf("%s",s);
    if(s[0]=='>'||s[0]=='}'||s[0]==']'||s[0]==')')
    {
        printf("Impossible\n");
        return 0;
    }
    int len=strlen(s),change=0,now=0;
    for(int n=0;n<len;n++)
    {
        if(s[n]=='<')
            l[++now]=s[n];
        if(s[n]=='{')
            l[++now]=s[n];
        if(s[n]=='[')
            l[++now]=s[n];
        if(s[n]=='(')
            l[++now]=s[n];
        if(s[n]=='>'||s[n]=='}'||s[n]==']'||s[n]==')')
        {
            if(now==0)
            {
                printf("Impossible\n");
                return 0;
            }
            if((l[now]=='<'&&s[n]!='>')||(l[now]=='('&&s[n]!=')')||(l[now]=='{'&&s[n]!='}')||(l[now]=='['&&s[n]!=']')) 
                change++;
            now--;
        }
    }
    if(now>0)
    {
        printf("Impossible\n");
        return 0;
    }
    printf("%d\n",change);
    return 0;
}
/*
好像是个栈 一年前老师讲过 然后忘了QAQ
自己的方法一直在第10个点上WA
然后发现没有考虑左括弧多余。。。
然后就在第11个点上WA了。。。
突然发现括弧好像是不可以交叉([)]  X
所以只能跟离他最近的括弧匹配 QAQ
考试的时候不会打栈
数组模拟栈
*/

后来自己还是打了个栈

#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
#define MAXN 1000005
char s[MAXN];
stack<char> t;
bool pd(char a,char b)
{
    if(a=='('&&b==')')
        return 1;
    if(a=='<'&&b=='>')
        return 1;
    if(a=='['&&b==']')
        return 1;
    if(a=='{'&&b=='}')
        return 1;
    return 0;
}
int main()
{
    scanf("%s",s);
    if(s[0]=='>'||s[0]=='}'||s[0]==']'||s[0]==')')
    {
        printf("Impossible\n");
        return 0;
    }
    int len=strlen(s),ans=0;
    for(int i=0;i<len;i++)
    {
        if(s[i]=='<'||s[i]=='['||s[i]=='{'||s[i]=='(')
            t.push(s[i]);
        if(s[i]=='>'||s[i]=='}'||s[i]==']'||s[i]==')')
        {
            if(t.size()==0)
            {
                printf("Impossible\n");
                return 0;
            }
            else if(pd(t.top(),s[i])==0)
                ans++;
            t.pop();
        }
    }
    if(t.size())
    {
        printf("Impossible\n");
        return 0;
    }
    printf("%d\n",ans);
    return 0;
}

D

给出n个线段问至少被覆盖k次的点的集合(实际就是求区间,这里这么描述只是表示这个区间不一定在输入里出现过)

给每个点排个序(相当于放在数轴上),标记是左端点还是右端点,设置一个cnt变量,遇到左端点+1,右端点-1,cnt==k时说明是一个答案区间的断点,同样设置一个标记变量,标记这应该是答案区间的左端点还是右端点。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<pair<int,int> > v;
vector<int> ans;
int n,k;
int main()
{
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        int l,r;
        scanf("%d %d",&l,&r);
        v.push_back(make_pair(l,-1));
        v.push_back(make_pair(r,1));
    }
    sort(v.begin(),v.end());
    int cnt=0;
    for(int i=0;i<v.size();i++)
    {
        if(v[i].second==-1)
        {
            ++cnt;
            if(cnt==k)
                ans.push_back(v[i].first);
        }
        else
        {
            if(cnt==k)
                ans.push_back(v[i].first);
            --cnt;
        }
    }
    printf("%d\n",ans.size()/2);
    for(int i=0;i<ans.size();i+=2)
        printf("%d %d\n",ans[i],ans[i+1]);
    return 0;
}

但是要注意的是 这道题如果碰到起点跟终点在同一个位置,则起点要排在终点的前面
STL的vector的sort是双关键字排序,就是如果first相等,他会自动按second升序排序,而如果自己手打结构体排序的话,就要注意!

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define MAXN 1000005
#define LL long long
int n,k;
struct node{
    int val,typ;
}a[MAXN*2];
vector<int>ans;
bool cmp(node p,node q)
{
    if(p.val<q.val)
        return 1;
    if(p.val==q.val)
        return p.typ>q.typ;
    return 0;
}
int main()
{
    scanf("%d %d",&n,&k);
    for(int i=0;i<n;i++)
    {
        scanf("%d %d",&a[i].val,&a[i+n].val);
        a[i].typ=1,a[i+n].typ=-1;
    }
    sort(a,a+2*n,cmp);
    int cnt=0;
    for(int i=0;i<2*n;i++)
    {
        if(a[i].typ==1) cnt++;
        if(cnt==k) ans.push_back(a[i].val);
        if(a[i].typ==-1) cnt--;
    }
    printf("%d\n",ans.size()/2);
    for(int i=0;i<ans.size();i+=2)
        printf("%d %d\n",ans[i],ans[i+1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/CQBZLYTina/article/details/81976418