qbxt 提高精英班 Day 1下午考试 题解

T1

模拟题,没什么可以说的。。。
直接暴力找就可以。。。唯一A掉的题
但是std写的比我少很多。。。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
int wpcnt,wgcnt,t1,t2;
unsigned short int mapp[4][4],apr[27];
bool winp[27],wing[27][27];
//先看两条对角线,然后看列、行 
void clr()
{
    memset(apr,0,sizeof apr);
}
void judge1(int x,int y)//个人获胜 
{
    //cout<<x<<' '<<y<<' '<<mapp[x][y]<<' '<<winp[mapp[x][y]]<<'\n';
    if(!winp[mapp[x][y]])
    {
            winp[mapp[x][y]]=1;
            ++wpcnt;
    }
}
void judge2()//团队获胜 
{
    if(!wing[t1][t2])
    {
            wing[t1][t2]=1;
            wing[t2][t1]=1;
            ++wgcnt;
    }
}
short int judge(short int x,short int y)
{
    if(apr[mapp[x][y]]==3)
     return 1;
    if(apr[mapp[x][y]]==2)
     return 2;
    return 0;
}
int main()
{
    freopen("count.in","r",stdin);
    freopen("count.out","w",stdout);
    int temp;
    char c;
    For(i,1,3)
     For(j,1,3)
     {
        while((c=getchar())==' '||c=='\n'||c=='\r');
        mapp[i][j]=c-'A'+1;
     }
    //右斜对角线
    For(i,1,3)
    {
        apr[mapp[i][i]]++;
    }
    temp=judge(1,1);
    if(temp==1)
    {
        judge1(1,1);
    }
    else if(!temp)
     temp=judge(2,2);
    if(temp==2)
    {
        For(i,1,3)
        {
            if(apr[mapp[i][i]]==1)
             t2=mapp[i][i];
            else
             t1=mapp[i][i];
        }
        judge2();
    }
    //cout<<temp<<'\n';
    clr();
    //左斜对角线 
    for(int i=1;i<=3;++i)
        apr[mapp[i][4-i]]++;
    temp=judge(1,3);
    if(temp==1)
    {
        judge1(1,3);
    }
    else if(!temp)
        temp=judge(2,2);
    if(temp==2)
    {
        For(i,1,3)
        {
            if(apr[mapp[i][4-i]]==1)
             t2=mapp[i][4-i];
            else
             t1=mapp[i][4-i];
        }
        judge2();
    }
    //行 
    For(i,1,3)
    {
        clr();
        For(j,1,3)
        {
            apr[mapp[i][j]]++;
        }
        temp=judge(i,1);
        if(temp==1)
        {
            judge1(i,1);
        }
        else if(!temp)
         temp=judge(i,2);
        if(temp==2)
        {
            For(j,1,3)
            {
                if(apr[mapp[i][j]]==1)
                 t2=mapp[i][j];
                else
                 t1=mapp[i][j];
            }
            judge2();
        }
    }
    //列 
    For(i,1,3)
    {
        clr();
        For(j,1,3)
         apr[mapp[j][i]]++;
        temp=judge(1,i);
        if(temp==1)
        {
            judge1(1,i); 
        }
        else if(!temp)
         temp=judge(2,i);
        if(temp==2)
        {
            For(j,1,3)
            {
                if(apr[mapp[j][i]]==1)
                 t2=mapp[j][i];
                else
                 t1=mapp[j][i];
            }
            judge2();
        }
    }
    cout<<wpcnt<<'\n'<<wgcnt;
    return 0;
}

T2

一个贪心题目,想法比较简单,显然我们需要把更多的时间留给高处的ci大的景点,sort一遍然后递推来做就可以
但是

一定要开long long

我想省一下空间结果弄巧成拙丢了50分- -
(不然就不用去买耳机了,真让人难过)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#define For(i,l,r) for(int i=l;i<=r;++i)
using namespace std;
inline long long int read()
{
    char c;
    bool t=0;
    long long int a=0;
    while((c=getchar())==' '||c=='\n'||c=='\r');
    if(c=='-')
    {
        t=1;
        c=getchar();
    }
    while(isdigit(c))
    {
        a*=10;
        a+=(c-'0');
        c=getchar();
    }
    return a*(t?-1:1);
}
struct point{
    long long int x,c;
}jd[100001];
bool cmp(point a,point b)
{
    return a.c>b.c?1:0;
}
long long int l,n,va,vb,temp;
long long ans;
int main()
{
    freopen("max.in","r",stdin);
    freopen("max.out","w",stdout);
    long long int nowh=0,preh=0;
    l=read();
    n=read();
    va=read();
    vb=read();
    temp=va-vb;
    For(i,1,n)
    {
        jd[i].x=read();
        jd[i].c=read();
    }
    sort(jd+1,jd+n+1,cmp);
    For(i,1,n)
    {
        if(nowh<jd[i].x)
        {
            preh=nowh;
            nowh=jd[i].x;
            ans+=(temp*(nowh-preh)*jd[i].c);
        }
    }
    printf("%lld",ans);
    return 0;
}

T3

一个比较难的动态规划题
但是考试的时候居然理解成重叠部分了。。。然后就看了两个小时,不然怎么也能拿30分搜索分。。。
以后还是要认真读题。。。

讲个思路吧。。。
先按左端点排序
既然是并集,那么我们就一定不会选那些被其他线段包含掉的小线段,所以我们先把那些被包含掉的线段都删掉,代码实现玄学
然后我们以线段序号数和用了的线段数为状态来dp
dp[i][k]=dp[j][k-1]+__________
去掉后剩下的线段就是这种情况
样例图片
这样看有两种情况
一种是一条和另一条有交集,另一种就是没有交集
①对于像(2,3)这种有重叠部分的线段,我们的状态转移方程是
dp[i][k]=dp[j][k-1]+r[i]-r[j]
②对于(1,3)这种没有重叠的,我们的状态转移方程是
dp[i][k]=dp[j][k-1]+r[i]-l[i]
显然,对于确定的i,k,r[i] 和 l[i]是不会变的,我们要做的只是找出
dp[j][k-1]和dp[j][k-1]-r[j]的最大值
可以预处理出最大值,然后直接调用
暴力不预处理的话单次寻找是O(n),全部状态O(nk)
所以复杂度是O(k n^2)
优化一下可以做到O(k n log n)
然后说可以用单调队列来优化。。。但是没有讲。。。

猜你喜欢

转载自blog.csdn.net/suxuyu01/article/details/81056189