算法训练(五)

1.gym 101755A

a=c⋅g,b=d⋅g,s=a+b=(c+d)⋅g 故若g%s==0且s>g则a=g,b=s−g显然符合条件,否则无解

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100001;
int main()
{
    int s,g;
    while(~scanf("%d%d",&s,&g))
        if(s%g!=0||s==g)printf("-1\n");
        else printf("%d %d\n",g,s-g); 
    return 0;
}
 

2.gym- 101755B

显然组成三角形面积最小时三个顶点应该是相邻的三个点,求出这nn个由相邻三个顶点组成的三角形面积维护最小值即为答案

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=200005;
int n,x[maxn],y[maxn];
ll S(int x0,int y0,int x1,int y1)
{
    return abs((ll)x0*y1-(ll)x1*y0);
}
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)scanf("%d%d",&x[i],&y[i]);
        x[n]=x[0],y[n]=y[0];
        x[n+1]=x[1],y[n+1]=y[1];
        ll ans=4e18+5;
        for(int i=0;i<n;i++)
            ans=min(ans,S(x[i+1]-x[i],y[i+1]-y[i],x[i+2]-x[i],y[i+2]-y[i]));
        printf("%I64d\n",ans);
    }
    return 0;
}
 

3.gym 101755C

把所有区间按右端点升序排,右端点相同则按左端点升序排,每次买第一个区间的右端点即可,这样后面的区间只要左端点不超过该右端点就都不用买

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f,maxn=200005;
int n,ans[maxn],res;
struct node
{
    int id,l,r;
    bool operator<(const node &b)const
    {
        if(r!=b.r)return r<b.r;
        return l<b.l;
    }
}a[maxn];
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)scanf("%d%d",&a[i].l,&a[i].r),a[i].id=i+1;
        sort(a,a+n);
        res=0;
        ans[res++]=a[0].r;
        for(int i=1;i<n;i++)
            if(a[i].l<=ans[res-1])continue;
            else ans[res++]=a[i].r;
        printf("%d\n",res);
        for(int i=0;i<res;i++)printf("%d%c",ans[i],i==res-1?'\n':' ');
    }
    return 0;
}
 

4.gym 101755E

只需要找到需要比较的区间L,R,在这个区间内比较一下是否为相反的子串,就可以了。

#include <cstdio>
#include <string>
#include<cstring>
using namespace std;
int main()
{
    char s[200005];
    char t[200005];
    while(~scanf("%s %s",&s,&t))
    {
        int n = strlen(s);
        int l = 0, r = n;
        for(int i = 0; i < n; i ++)
        {
            if(s[i] == t[i]) l++;
            else break;
        }
        for(int i = n; i >= 0; i --)
        {
            if(s[i]== t[i]) r --;
            else break;
        }
        //cout << l << " " << r << endl;
        int f = 0;
        for(int i = l; i <= r; i ++)
        {
            if(s[i] != t[r + l - i])
            {
                f= 1;
                break;
            }
        }
        if(f==0)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

5.gym 101755J

统计每个长度出现的次数numinumi,答案即为⌊∑⌊numi2⌋2⌋

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=200001;
int n,a[maxn];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int temp;
        scanf("%d",&temp);
        a[temp]++;
    }
    int ans=0;
    for(int i=1;i<=200000;i++)ans+=a[i]/2;
    printf("%d\n",ans/2);
    return 0;
}
 

6.gym 101755L

由于只是判断tt是否为ss的子序列,故贪心的用尽可能ss串靠前的字符取匹配tt,以Nex[i][j]Nex[i][j]表示ss串的第ii个字符后面第jj个字母第一次出现的位置,在匹配过程中记录tt串的每个字符在ss串中的对应匹配位置,每次加入新字符jj时,考虑之前tt串的最后一个字符在ss串的匹配位置ii,如果next[i][j]next[i][j]有合法值那么说明tt依旧是ss的子序列,否则不是
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=200005;
int n,q,Next[maxn][26],pos[26],ans[maxn];
char s[maxn],op[10];
int main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    memset(Next,-1,sizeof(Next));
    memset(pos,-1,sizeof(pos));
    for(int i=n;i>=0;i--)
    {
        for(int j=0;j<26;j++)Next[i][j]=pos[j];
        pos[s[i]-'a']=i;
    }
    scanf("%d",&q);
    int m=0,len=0;
    ans[0]=0;
    while(q--)
    {
        scanf("%s",op);
        if(op[1]=='u')
        {
            scanf("%s",op);
            if(ans[m]!=-1&&Next[ans[m]][op[0]-'a']!=-1)ans[m+1]=Next[ans[m]][op[0]-'a'],m++,len++;
            else ans[++m]=-1;
        }
        else m--,len=min(len,m);
        if(len==m)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
 

7.gym 101755M

由于每个串和ss至多差一个字符,那么aa和b,cb,c分别至多差两个字符,找出aa字符串与b,cb,c字符串不同的位置,显然不同的位置数不超过33个,否则无解,首先判断aa本身是不是合法解,然后枚举这三个位置中的一个为aa和ss相异的位置,然后枚举该位置的字符判断是否有解,统计解的数量即可
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=200005;
char s[3][maxn];
int n,vis[maxn];
bool check()
{
    for(int i=1;i<=2;i++)
    {
        int num=0;
        for(int j=0;j<n;j++)
            if(s[0][j]!=s[i][j])
            {
                num++;
                if(num>1)return 0;
            }
    }
    return 1;
}
int main()
{
    for(int i=0;i<3;i++)scanf("%s",s[i]);
    n=strlen(s[0]);
    int m=0,flag=1,pos[10];
    for(int i=1;i<=2;i++)
    {
        for(int j=0;j<n;j++)
            if(s[0][j]!=s[i][j])vis[j]=1;
    }
    for(int i=0;i<n;i++)
        if(vis[i])
        {
            pos[m++]=i;
            if(m>4)break;
        }
    if(m>3)flag=0;
    int ans=0,anspos;
    char ansc;
    if(flag)
    {
        if(check())ans++,anspos=0,ansc=s[0][0];
        for(int i=0;i<m;i++)
        {
            char t=s[0][pos[i]];
            for(int j=0;j<26;j++)
                if('a'+j!=t)
                {
                    s[0][pos[i]]='a'+j;
                    if(check())ans++,anspos=pos[i],ansc=j+'a';
                }
            s[0][pos[i]]=t;
        }
        if(ans==0&&m)flag=0;
        if(m==0)ans=2;
    }
    if(!flag)printf("Impossible\n");
    else if(ans>1)printf("Ambiguous\n");
    else 
    {
        s[0][anspos]=ansc;
        printf("%s\n",s[0]);
    }
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值