Cs Round#56 D Find Path Union

题意:有一棵如下的完全二叉树,求所有给定结点到根节点的路径的并有多少条边。

一开始联想到线段树,发现结点的排布很像线段树的标号。于是模仿线段树敲了一下,交上去发现3个点MLE了。。。

无心优化,跑去看题解。题解的思路是自底向上,先将询问的结点排序,最后从最深的节点开始往上递推,记录每层开始分叉的结点,统计答案即可

正解:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
vector<LL>a;
queue<LL>q;
int n,ans=0;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        LL x;
        scanf("%lld",&x);
        a.push_back(x);
    }
    sort(a.begin(),a.end());
    while(a.size()||!q.empty()){
        LL maxn;
        if(!a.size())maxn=q.front();
        else if(q.empty())maxn=a.back();
        else maxn=max(q.front(),a.back());
        ans++;
        if(maxn>>1)q.push(maxn>>1);
        while(!q.empty()&&maxn==q.front())q.pop();
        while(a.size()&&maxn==a.back())a.pop_back();
    }
    printf("%d\n",ans-1);
    return 0;
}

76.92 points:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
map<uLL,bool>vis;
unsigned int n,ans=0;
uLL pw[62];
void form(){
    pw[0]=1;
    for(int i=1;i<=61;i++)pw[i]=1ll*pw[i-1]*2;
    for(int i=1;i<=61;i++)pw[i]--;
}
void query(uLL k,uLL l,uLL r,uLL x){
    //printf("%d\n",k);
    if(!vis[k]){
        ans++;
        vis[k]=1;
    }
    if(l==r)return;
    int mid=(l+r)>>1;
    if(x<=mid)query(k<<1,l,mid,x);
    else query(k<<1|1,mid+1,r,x);
}
int main(){
    form();
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        uLL x;
        int t;
        scanf("%llu",&x);
        t=lower_bound(pw+1,pw+61,x)-pw;
        //printf("%d\n",t);
        query(1,1,1<<(t-1),x-pw[t-1]);
    }
    printf("%d\n",ans-1);
    return 0;
}
时间: 2024-08-08 11:17:46

Cs Round#56 D Find Path Union的相关文章

CSA Round #56

C.Find Path Union 题意 给一颗n个节点数,给出每个节点所连接的点,以及连接的顺序,问能不能找到一种合适的连接方案使得若有节点的连接顺序都满足 分析 其实就是模拟题, 构造取的这个过程,每次取的时候, 考虑取得这个点,顺序是否满足,用一个队列模拟这个一个一个取的过程,若最后都按照满足的顺序取完则可以,反之则无解 #include <bits/stdc++.h> using namespace std; int main(int argc, char *argv[]) { cin

CH Round #56 - 国庆节欢乐赛解题报告

最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树,其中一些树上结有能够产生能量的魔力水果.已知每个水果的位置(Xi,Yi)以及它能提供的能量Ci.然而,魔幻森林在某些时候会发生变化:(1) 有两行树交换了位置.(2) 有两列树交换了位置.当然,树上结有的水果也跟随着树一起移动.不过,只有当两行(列)包含的魔力水果数都大于0,或者两行(列)都没有魔

Multidimensional Queries(二进制枚举+线段树+Educational Codeforces Round 56 (Rated for Div. 2))

题目链接: https://codeforces.com/contest/1093/problem/G 题目: 题意: 在k维空间中有n个点,每次给你两种操作,一种是将某一个点的坐标改为另一个坐标,一种操作是查询[l,r]中曼哈顿距离最大的两个点的最大曼哈顿距离. 思路: 对于曼哈顿距离,我们将其绝对值去掉会发现如下规律(以二维为例): 故这题我们可以用线段树来维护[l,r]中上述每种情况的最大值和最小值,用二进制来枚举xy的符号(1为正,0为负),最后答案是 每种情况中区间最大值-区间最小值

BestCoder Round #56 1002 Clarke and problem 1003 Clarke and puzzle

今天第二次做BC,不习惯hdu的oj,CE过2次... 1002 Clarke and problem #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<queue> #include<vector> #include<stack> #include<vector> #include<map>

CS Round#49 C Max Substring

Max Substring Time limit: 1000 msMemory limit: 256 MB You are given a string S. Find a string T that has the most number of occurrences as a substring in S. If the solution is not unique, you should find the one with maximum length. If the solution i

BestCoder Round #56 /hdu5464 dp

Clarke and problem 问题描述 克拉克是一名人格分裂患者.某一天,克拉克分裂成了一个学生,在做题. 突然一道难题难到了克拉克,这道题是这样的: 给你nn个数,要求选一些数(可以不选),把它们加起来,使得和恰好是pp的倍数(00也是pp的倍数),求方案数. 对于nn很小的时候,克拉克是能轻易找到的.然而对于nn很大的时候,克拉克没有办法了,所以来求助于你. 输入描述 第一行一个整数T(1 \le T \le 10)T(1≤T≤10),表示数据的组数. 每组数据第一行是两个正整数n,

BestCoder Round #56/hdu5463 Clarke and minecraft 水题

Clarke and minecraft 问题描述 克拉克是一名人格分裂患者.某一天,克拉克分裂成了一个游戏玩家,玩起了minecraft.渐渐地,克拉克建起了一座城堡. 有一天,克拉克为了让更多的人分享自己的成果,开了局域网,并且选择创造模式.不幸的是,这一天有一个熊孩子进了克拉克的游戏,他在克拉克的城堡里放了很多个爬行者!当刚刚去外面打怪回.开着生存模式的克拉克回到城堡中的一瞬间,爬行者们突然自爆......(自行脑部画面)于是克拉克的城堡变成了一片废墟,圆石.木板.砖块等建筑材料撒落了一地

HDU5465/BestCoder Round #56 (div.2) 二维树状数组

Clarke and puzzle 问题描述 克拉克是一名人格分裂患者.某一天,有两个克拉克(aa和bb)在玩一个方格游戏. 这个方格是一个n*mn∗m的矩阵,每个格子里有一个数c_{i, j}c?i,j??. aa想开挂,想知道如何打败bb. 他们要玩qq次游戏,每一次做一次操作: 1. 取出当中的一个子矩阵(x_1, y_1)-(x_2, y_2)(x?1??,y?1??)−(x?2??,y?2??)玩游戏.两个人轮流行动,每一次只能从这个子矩阵中的一个方格c_{i, j}c?i,j??中减

CS Round #50 Min Races(nlogn级别的LDS)

题目链接:点——点 题意:n个比赛者,每个比赛者都有自己的班级(似乎是这样翻译,就像实力至上的教室那里面的A,B,C班一样,1班最强...),和自己在n名选手中能排到的名次. 如果名次排在自己前面的选手的班级更厉害(比如1班就比2班强,废话...),那么这个选手自己心里就觉得自己赢了. 题解:看了好久的题目才理解它要问什么.简单来说,先按照名次排个序,然后去取最长递增序列,把每个人都遍历过,然后算出有几条就可以了.(这个其实反过来就是求最长递减子序列) 给出的n达到1e5,所以肯定不能直接dp,