牛客编程巅峰赛S2第10场 - 钻石&王者 题解

A题:
作者成功地把所有的错误做法都试了一遍。
因为数只能往后移,所以在当前数后面有比它小的数的时候,这个数肯定要往后移,不然的话就没有机会往后移了。
所以,我们只要维护一个后缀最小值即可。
代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int整型 
     * @param a int整型vector 
     * @return int整型
     */
    int wwork(int n, vector<int>& a) {
        int s=a.back(),ans=0;
        for(int i=n-2;i>=0;i--){
            if(a[i]>s)ans++;
            else s=a[i];
        }
        return ans;
    }
};

时间复杂度 O(n)

B题:
把表打出来后,通过手算或用OEIS找到规律即可。
规律就是 f[i]=i+f[i/2]*2 (i/2向下取整)
代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int整型 
     * @return long长整型
     */
    long long calc(int x){
        if(x==1)return 1;
        return x+calc(x/2)*2;
    }
    long long Sum(int n){
        return calc(n);
    }
};

时间复杂度 O(log n)

C题:
逐位处理。因为 图片说明 ,所以可以枚举位数k从0到20进行处理。
我们定义,当两个点之间的路径第k位都为1时,就称这两个点之间可以抵达。
如果两条边相连点x,y,若p[x]和p[y]在二进制表示下的第k位都为1,那么说明x可以抵达的任何点都可以可以抵达y可以抵达的任何点,所以用并查集维护集合。
然后求出每个集合的大小,用siz来表示。
最后对于同一个集合内的任何点,他们之间都可以相互抵达,进行计算即可。注意要特殊处理路径为单个点的情况
代码如下:

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 
     * @param n int整型 点的个数
     * @param u int整型vector 每条边的起点
     * @param v int整型vector 每条边的终点
     * @param p int整型vector 每个点的价值
     * @return long长整型
     */
    long long fa[100010],siz[100010],v[100010];
    int get(int x){
        if(x==fa[x])return x;
        return fa[x]=get(fa[x]);
    }
    long long solve(int n, vector<int>& u, vector<int>& v, vector<int>& p) {
        long long ans=0,s=1;
        for(int k=0;k<=20;k++){
            for(int i=0;i<n;i++){
                fa[i]=i;
                siz[i]=0;
            }
            for(int i=0;i<n-1;i++)
                if(p[u[i]]>>k&1&&p[v[i]]>>k&1){
                    int x=get(u[i]),y=get(v[i]);
                    if(x==y)continue;
                    fa[x]=y;
                }
            for(int i=0;i<n;i++)
                siz[get(i)]++;
            for(int i=0;i<n;i++)
                if(fa[i]==i&&p[i]>>k&1)ans=ans+(siz[i]+1)*siz[i]/2*s;
            s=s*2;
        }
        return ans;
    }
};

时间复杂度 O(n log n)

全部评论

相关推荐

感觉这一周太梦幻了,就像一个梦,很不真实~~~感觉这个暑期,我的运气占了99成,实力只有百分之一4.15上午&nbsp;腾讯csig&nbsp;腾讯云部门,面完秒进入复试状态4.16下午&nbsp;美团优选供应链部门,4.18上午发二面4.17晚上&nbsp;阿里国际一面,纯拷打,面完我都玉玉了4.18下午&nbsp;阿里国际二面,是我们leader面的我,很轻松~~4.18晚上&nbsp;约了hr面4.19上午&nbsp;hr面,下午两点口头oc4.19晚上&nbsp;意向书说起来我的暑期好像一次都没挂过~~~~~难道我是天生面试圣体?----------------------------------------------------------------------六个月前,我还是0项目0刷题,当时想的是先把论文发出来再去找实习。结果一次组会,老师打破了我的幻想(不让投B会,只让投刊或者A)我拿头投啊!!!然后就开始物色着找实习,顺便做完了mit的6.s081,但是基本上还是没刷过题目-----------------------------------------------------------------------11月&nbsp;&nbsp;一次偶然的机会,面进了某个耳机厂的手环部门,大概是做嵌入式的,用的是CPP。12月&nbsp;莫名其妙拿到了国创的面试机会,0基础四天速成java基础!居然也给我面过了hhhhh,可能是面试没写题吧入职国创后的几个月,一直没活,天天搁那看剧,都快忘了还有暑期实习这回事了~~~~命运的齿轮在2.26开始转动,因为这一天美团开了,我开始慌了,因为那时的我什么都不会。lc,八股,sql全部是0进度。然后就开始了女娲补天,上班刷题,下班继续做之前的开源,顺便学一学八股。3月到现在,lc也刷到快200了,一天最多提交了47次~~~~~~~~~~八股根据别人的面经总结和博客,写了快十万字的笔记~~~~~~~~~~简历上的实习经历和开源,也努力去深挖了,写了几万字的记录~~~~~~所以面试的时候,基本上都能cover了,面试官问到的基础基本都会,不基础的我就把他往我会的地方引。结果好像还不错,基本上每个面试官评价都挺好的emmmmmmmm
投递阿里巴巴等公司10个岗位
点赞 评论 收藏
转发
1 收藏 评论
分享
牛客网
牛客企业服务