首页 > 其他分享 >Codeforces 1806E Tree Master

Codeforces 1806E Tree Master

时间:2024-02-20 15:35:54浏览次数:34  
标签:int Tree Codeforces sqrt i64 maxn Master calc id

考虑一个最基础的暴力,就是直接记忆化搜索暴力往上跳。
但是能发现如果一层的节点数过多,状态数太多,就寄了。

再考虑一个基础的暴力,就是直接跳。
但是如果要跳的层数过多,就寄了。

考虑结合一下,根号分治。
对于一层内节点数 \(\le \sqrt{n}\) 的记录下每两个点间的答案。
对于节点数 \(> \sqrt{n}\) 的节点暴力往上跳跳到一个已经得到的状态即可。

复杂度证明:
对于状态数,相当于是求 \(\max\{\sum\limits d_i^2\}(\sum\limits d_i = n, d_i\in \mathbb{N})\),因为有 \(x^2 + y^2 \ge (x + 1)^2 + (y - 1)^2(x < y)\),所以肯定是当 \(d_i = \sqrt{n}\) 时取到 \(\max\),值为 \(n\sqrt{n}\),所以状态数是 \(O(n\sqrt{n})\) 的。
对于 \(> \sqrt{n}\) 的层,最多只会有 \(\sqrt{n}\) 层,就最多会往上跳 \(\sqrt{n}\) 次,复杂度 \(O(q\sqrt{n})\)。

综上,时间复杂度 \(O(n\sqrt{n} + q\sqrt{n})\)。

#include<bits/stdc++.h>
using i64 = long long;
const int maxn = 1e5 + 10, B = 300;
i64 a[maxn];
int fa[maxn], dep[maxn];
std::vector<int> P[maxn];
i64 ans[maxn][B + 10];
int id[maxn];
bool vis[maxn];
inline i64 calc(int x, int y) {
    if (vis[dep[x]]) return ans[x][id[y]];
    return calc(fa[x], fa[y]) + a[x] * a[y];
}
int main() {
    int n, q; scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    for (int i = 2; i <= n; i++) scanf("%d", &fa[i]), P[dep[i] = dep[fa[i]] + 1].push_back(i);
    ans[1][1] = a[1] * a[1], vis[0] = 1, id[1] = 1;
    for (int i = 1; i <= n; i++) {
        if (P[i].size() > B) continue;
        int c = 0;
        for (int x : P[i]) id[x] = ++c;
        for (int x : P[i]) for (int y : P[i]) ans[x][id[y]] = calc(x, y);
        vis[i] = 1;
    }
    while (q--) {
        int x, y; scanf("%d%d", &x, &y);
        printf("%lld\n", calc(x, y));
    }
    return 0;
}

标签:int,Tree,Codeforces,sqrt,i64,maxn,Master,calc,id
From: https://www.cnblogs.com/rizynvu/p/18023214

相关文章

  • Codeforces Round 928(Div. 4)
    Dashboard-CodeforcesRound928(Div.4)-Codeforces第一次参加CF,最后一道题连题都没读,下次不会就跳,菜是原罪A:找字符串中A,B数量,遍历一下最后比较即可B:判断是三角形还是正方形,题目表示除了正方形就是三角形,所以直接判断是不是正方形,用ans数组记录每一行1的个数,然后从大......
  • Codeforces Round 900 (Div. 3)
    题目A.只要k出现过就是YES#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=1e5+10;#defineinf0x3f3f3f3fvoidsolve(){intn,k;cin>>n>>k;map<int,int>mp;for(inti=0,x;i<n;i++){cin......
  • Codeforces Round 928 (Div. 4) (小白的复盘)
    A.VladandtheBestofFive思路:给你一个长度字符串只包含A和B输出最多的字符解法:按题意来Code:#include<bits/stdc++.h>usingnamespacestd;intmain(){intt;cin>>t;while(t--){strings;cin>>s;intcnt=0;fo......
  • Codeforces Round 928 (Div. 4)(A、B、C、D、E、G)
    目录ABCDEGA统计A、B输出#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(inti=(a);i>=(b);--i)#definepiipair<int,int>#definelllonglong#definedbdouble#de......
  • Codeforces Round 928 (Div. 4)
    总结一下最近:感觉过于追求进度了,没有好好的把每题都吃透消化,然后有点依赖题解了,没有好好的思考...B.VladandShapesB题输入二维数组的时候不可以直接两个for循环然后cin,要读入char,再转为数字赋值给二维数组,因为他读入的时候不带有空格而int是要有空格的,这样子比如读000就把它......
  • Sasha and the Happy Tree Cutting
    题目只出现了一些关键点,所以想到虚树,我们对关键点建立虚树,会发现对虚树上的一条边\((u,v)\),在原图中\(u\)到\(v\)的路径只用最多选择一条就可以了,所以我们就发现,有效的边的个数就是虚树上的边,是\(O(k)\)的然后看一下\(k\)的范围,想到状态压缩,对每一个状态\(S\),枚举虚树中的每一条......
  • Java集合篇之set,面试官:请说一说HashSet、LinkedHashSet、TreeSet的区别?
    写在开头Java的集合世界中主要由List,Set,Queue,Map构成,我们在之前的博文中已经学习了List,接下来我们继续学习Set集合。Set特点:存取无序,不可以存放重复的元素,不可以用下标对元素进行操作HashSet作为Set容器的代表子类,HashSet经常被用到,我们通过源码去分析它【源码查看】public......
  • Codeforces Round 924 (Div. 2)
    目录写在前面ABCDEF写在最后写在前面比赛地址:https://codeforces.com/contest/1928。终于把欠下的一堆题补上了呃呃天使骚骚共通线什么构式呃呃,一周目就想走老师线直通单身笑死我了。A签到。发现等分后重新拼接可以得到\(\frac{x}{2}\times2y\)与\(\frac{y}{2}\times2......
  • Codeforces Round 927 (Div. 3)(A~F)
    目录ABCDEFA第一个遇到连续两个荆棘的地方就不能再赢金币了。所以统计连续两个荆棘之前的所有金币#include<bits/stdc++.h>#defineintlonglong#definerep(i,a,b)for(inti=(a);i<=(b);++i)#definefep(i,a,b)for(inti=(a);i>=(b);--i)#definepiipai......
  • Codeforces Round 927 (Div. 3)
    CodeforcesRound927(Div.3)A-ThornsandCoins解题思路:出现连续两个障碍之前,所有金币都能拿到。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecondusingi128=__int128_t;......