zoukankan      html  css  js  c++  java
  • Codeforces Round #635 (Div. 2)

    地址:http://codeforces.com/contest/1337

         题意:给出a,b,c,d。从a~b~c~d三个区间内各找一个数,构成三角形。

         解析:根据三角形的性质,输出a,c,c是一个可行解。记得从小到大输出,wa了1次。

    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    const int inf = 0x3f3f3f3f;
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            ll a,b,c,d;
            cin>>a>>b>>c>>d;
            cout<<a<<" "<<c<<" "<<c<<endl;
        }
    }

         题意:x,n,m。龙有x滴血,有操作:血量/2+10 -> 最多n次。血量-10->最多m次。问是否能把龙杀掉

         解析:对于操作一,可以看出,当血量<20,/2+10这个值是要增大的。所以我们先进行操作一,当<20时break掉。然后把这个剩余血量-10*m,看是否小于0。

    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    const int inf = 0x3f3f3f3f;
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int x,n,m;
            cin>>x>>n>>m;
            int cnt=0;
            int k=x;
            for(int i=1;i<=n;i++)
            {    
                x=x/2+10;
                if(x<20)
                    break;
                k=x;                                
            }
        //    cout<<k<<endl;
            k=k-m*10;
            if(k>0)
                cout<<"NO"<<endl;
            else
                cout<<"YES"<<endl;
        }
    }

         题意:给出一个1~n点都含有的完整的树,只有一个根。每个点都是一个城市。现在要把k个城市变成工业城市,其他变成旅游城市。这些工业城市各出一个人去1号点,让他们沿途经过的旅游城市最大,输出这个值。

         解析:比赛时只纠结这个入度问题了,思维没有往外扩。这里不用考虑最短路的问题,因为这个树是没有环的。取k个点,第一个想到的,就是从深度最深的点开始取。深度是当前这个点到达1号点经过的点数,比如样例1,deep[5]=2。将深度从大到小排个序,在取的过程中,会出现一个问题,假设我取到了F点,那么它的子节点也一定被取了,那么子节点到1号点所经过的旅游城市数就变了。也就是说,取一个点,那么它的子节点到达1号点所经过的旅游城市数都要-1。所以需要记录点的子节点数size。那么每个点的贡献就是:deep[i]-(size[i]-1)。为什么-1呢,因为size[i]包含了i本身,算的时候要去掉。

          采用了链式前向星来存图,关于它,我推荐这位大佬的讲解:https://blog.csdn.net/sugarbliss/article/details/86495945

          关于求deep[]和size[]的过程,采用了dfs的回溯,即对一个点,找出它的所有子节点,然后再从子节点回到1号点,这中间把deep[]和size[]累加出来。这个过程需要自己好好体会的,这里为方便小白我给出样例1 的dfs过程:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<vector>
    #include<cmath>
    #include<string>
    #include<map>
    #include<queue>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    int head[maxn],deep[maxn],siz[maxn];
    int cnt=0;
    struct node
    {
        int to,nxt;
    }edge[4*maxn];
    void add(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].nxt=head[u];
        head[u]=cnt++;
    }
    void dfs(int u,int v,int d)
    {
        deep[u]=d;
        siz[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==v)
                continue;
            dfs(to,u,d+1);
            siz[u]+=siz[to];
        }
    }
    int main()
    {
        int n,k;
        memset(head,-1,sizeof(head));
        cin>>n>>k;
        int a,b;
        for(int i=1;i<n;i++)
        {
            cin>>a>>b;
            add(a,b);
            add(b,a);
        }
        dfs(1,-1,0);
        for(int i=1;i<=n;i++)
        {
            deep[i]-=(siz[i]-1);
        }
        sort(deep+1,deep+1+n);
        ll sum=0;
        int j=n;
        for(int i=1;i<=k;i++)
            {
                sum+=deep[j];
                j--;
            }
        cout<<sum<<endl;
    }

     

         题意:题意很简单,给出三组数,每组选一个,使(a-b)*(a-b)+(a-c)*(a-c)+(b-c)*(b-c)最小。

         解析:先想到的是暴力,但是复杂度太高O(n3)。所以可以考虑通过枚举其中一个数组,从另外两个数组中拿数来算最小值。观察一下这个式子,要想最小化,x,y,z三者的两两距离一定要最小。而且对于三者关系,无外乎就这六种关系:b>=a>=c  b>=c>=a  a>=b>=c  a>=c>=b  c>=a>=b  c>=b>=a。  举个例子,固定a数组的x,找出离它最近的y,z。可以通过二分查找,这里直接用了lower_bound()来找。找到y,z还不算完,因为我们要把上面那六种关系全弄一遍,固定一个数组,我们可以找到三种关系,当前例子即为:x>=y>=z  y>=x>=z   z>=x>=y   。把找x的这个数组换掉,固定另外俩数组,就可以把6种关系找全了!

              建议全开long long,避免不必要的错误。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const ll maxn=1e5+10;
    ll a[maxn],b[maxn],c[maxn];
    const ll inf=2e18+10;
    ll minn=inf;
    ll gett(ll a,ll b,ll c)
    {
        return (a-b)*(a-b)+(a-c)*(a-c)+(b-c)*(b-c);
    }
    void ac(ll a[],ll b[],ll c[],ll n1,ll n2,ll n3)  //固定a[],查找b[],c[]
    {
        for(int i=0;i<n1;i++)
        {
            ll p1,p2;
            p1=lower_bound(b,b+n2,a[i])-b;
            p2=lower_bound(c,c+n3,a[i])-c;
            if(p1==n2)    //如果没找到,就退到离a[i]最近的(b[i]<=a[i])
                p1--;
            if(p2==n3)
                p2--;
            if(p1>0)
                minn=min(minn,gett(a[i],b[p1-1],c[p2]));  //p1>0,防止-1越界。
            if(p2>0)
                minn=min(minn,gett(a[i],b[p1],c[p2-1]));    //同上
            minn=min(minn,gett(a[i],b[p1],c[p2]));
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            ll n1,n2,n3;
            minn=inf;
            scanf("%lld%lld%lld",&n1,&n2,&n3);
            for(int i=0;i<n1;i++)
                scanf("%lld",&a[i]);
            for(int i=0;i<n2;i++)
                scanf("%lld",&b[i]);
            for(int i=0;i<n3;i++)
                scanf("%lld",&c[i]);    
            sort(a,a+n1);
            sort(b,b+n2);
            sort(c,c+n3);
            ac(a,b,c,n1,n2,n3);
            ac(b,a,c,n2,n1,n3);
            ac(c,b,a,n3,n2,n1);
            cout<<minn<<endl;
        }
    }
  • 相关阅读:
    Oracle9使用oradata恢复数据库
    我该怎么安排下属的工作项目经理如何分配任务
    如果说中国的程序员技术偏低,原因可能在这里
    项目经理问:为什么总是只有我在加班 – 挂包袱现象
    【转】面试真经
    [JAVA]PING和TELNET用法介绍
    Hello World 你懂的
    线程间操作控件
    获取客户端相关信息
    winfrom 特效 [转载]
  • 原文地址:https://www.cnblogs.com/liyexin/p/12716741.html
Copyright © 2011-2022 走看看