codeforce : Educational Codeforces Round 22

来源:互联网 发布:飞机模拟驾驶软件 编辑:程序博客网 时间:2024/06/06 20:58

A. The Contest

题目大意:

输入一个整数n表示有n个数,然后输入n个数表示这小子解决每个题所用的时间,当然同一时间只能想一个问题,然后他得交题,然后输入m,然后输入m个有序对,表示m个时间段,每个用(l,r)表示,然后只能在l<=t<=r这个时间段内交题,任何一个瞬间只要在这个可交题时间范围内他可以交无数道题,然后让你求他交完所有题并ac的最短时间,假定他交的都是对的;

基本思路:

很自然想到把所有时间都加起来,然后交了一发,我就是个傻子,反应了一会才想起来可能不在某个时间段内,然后改,不停的错在样例7,11上,简直了,代码能力好差啊,果断看了室友的,我得提高代码能力,嗯,然后这也给自己提个醒,就是我扫一次可以只找看是否符合某一条件,这样虽然多扫几遍,但是能使思路清晰;总之分三种四种情况在第一段左边,在最后一段右边,做一段右边和该段下一段的左边,然后其实还有如果在某一段之间,这样不用改变sum,所以就不管了,然后问题圆满解决了;

代码如下:

#include<bits/stdc++.h>


using namespace std;


const int maxn = 1000+10;


int a[maxn],l[maxn],r[maxn];


int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    int m;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d",&l[i],&r[i]);
    }
    int sum=0;
    for(int i=0;i<n;i++)
    {
        sum+=a[i];
    }
    if(sum>r[m-1]) printf("%d\n",-1);
    else if(sum<l[0]) printf("%d\n",l[0]);
    else
    {
        for(int i=0;i<m-1;i++)
        {
            if(sum>r[i]&&sum<l[i+1])
                sum=l[i+1];
        }
        printf("%d\n",sum);
    }
    return 0;
}


B. The Golden Age

题目大意:

输入x,y,l,r,满足l<=x^a+y^b<=r,然后令t=x^a+y^b,该年就是非黄金年,然后就是让你求l和r之间的黄金年。 (2 ≤ x, y ≤ 10181 ≤ l ≤ r ≤ 1018).

基本思路:

即使各种二重循环 ,然后注意跳出循环的条件,然后由于0次幂也可以所以就是从1开始的,然后注意排序,然后里面如果有相同的也无所谓因为不会取到,然后就没有然后了;

代码如下:

#include<bits/stdc++.h>


using namespace std;


typedef long long ll;
vector<ll>v;


int main()
{
    ll x,y,l,r;
    scanf("%I64d%I64d%I64d%I64d",&x,&y,&l,&r);
    v.push_back(l-1);
    v.push_back(r+1);
    for(ll i=1;;i*=x)
    {
        for(ll j=1;;j*=y)
        {
            if(i+j>=l&&i+j<=r) v.push_back(i+j);
            if(j/y>r) break;
        }
        if(i/x>r) break;
    }
    sort(v.begin(),v.end());
    int sz=v.size();
    ll ans=0;
    for(int i=1;i<sz;i++)
    {
        ans=max(ans,v[i]-v[i-1]-1);
    }
    printf("%I64d\n",ans);
}


C. The Tag Game

题目大意:

输入n和m然后n代表有n个节点的一棵无向树,m代表男孩棋子的位置,女孩棋子的位置在1号节点,1号节点是根节点,然后后面n-1行输入两个数a和b,表示a和b之间有边相连,然后男孩想尽量多的走,女孩想尽量少的走,当女孩的棋子追上男孩的棋子时游戏结束,即他们的棋子位于同一点,然后然你求最多的步数;

基本思路:

这个题是个贪心,毫无疑问,但是怎么贪心呢,我就不会了,然后看大佬的代码是用dfs深搜了一下,其实一开始也想用深搜,就是想让一个人走一步,另一个人走一步,然后我是真的垃圾啊,我实现不了,然后接着我想到了一个不动另一个动,然后最后*2,但是我也不会实现,所以还是参考了大佬的代码,大佬的意思是,用一个f数组存每个节点的父节点,用一个h数组存储高度,然后用一个d数组存储从某一个点开始到树叶的最大深度,那么问题可以转化为女孩棋子从1节点到男孩棋子能到达最大深度的叶子的步数*2,那个用dfs的目的主要就是求d数组个元素的值,问题就基本解决了,然后还有一个问题就是,男孩的棋子向上到达他的父节点,然后从这个点出发能到达的最大深度更大,所以还要比较一下这个,这个放在一个循环里就好了,然后问题圆满解决;

代码如下:

#include<bits/stdc++.h>


using namespace std;


const int maxn = 200000+10;
int f[maxn],h[maxn],d[maxn];
vector<int>v[maxn];
int n,m;


void dfs(int x)
{
    int sz=v[x].size();
    for(int i=0;i<sz;i++)
    {
        int t=v[x][i];
        if(t!=f[x])
        {
            f[t]=x;
            h[t]=h[x]+1;
            dfs(t);
            d[x]=max(d[t]+1,d[x]);//回溯求最大深度;
        }
    }
    return;
}


int main()
{
    scanf("%d%d",&n,&m);
    int a,b;
    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d",&a,&b);
        v[a].push_back(b);
        v[b].push_back(a);
    }
    memset(f,0,sizeof(f));
    memset(h,0,sizeof(h));
    memset(d,0,sizeof(d));
    dfs(1);
    int ans=0,cnt=0;
    for(int i=m;i;i=f[i],cnt++)//看看向上走到父节点是否可以使步数更多;
    {
        if(h[i]>cnt)
        {
            ans=max(ans,h[i]+d[i]);
        }
    }
    printf("%d\n",ans*2);
}   {
        if(h[i]>cnt)
        {
            ans=max(ans,h[i]+d[i]);
        }
    }
    printf("%d\n",ans*2);
}

原创粉丝点击