关于时间复杂度的疑问

P3806 【模板】点分治 1

_WHITE_NIGHT_ @ 2024-10-18 20:46:14

Rt
请将我的代码复制到编辑器里,查看第102 - 108行

#include <bits/stdc++.h>
using namespace std;

namespace FastIO
{
    const int Mt = 1e5;
    inline char getch()
    {
        static char buf[Mt],*p1 = buf,*p2 = buf;
        return p1 == p2 && (p2 = (p1 = buf) + fread(buf,1,Mt,stdin),p1 == p2) ? EOF : *p1++;
    }

    inline int input()
    {
        int num = 0,f = 1;
        char ch = getch();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') f = -1;
            ch = getch();
        }
        while(ch >= '0' && ch <= '9')
        {
            num = (num << 1) + (num << 3) + (ch ^ 48);
            ch = getch();
        }
        return num * f;
    }

    inline void printNum(int num)
    {
        if(num >= 10) printNum(num / 10);
        putchar(num % 10 + 48);
    }

    inline void print(int num,char ch = ' ')
    {
        if(num < 0) putchar('-'),num = -num;
        printNum(num);
        putchar(ch);
    }
}
using namespace FastIO;

constexpr int N = 1e4 + 5;
constexpr int M = 1e7 + 5;
const int INF = -1u / 2;
struct Edge { int v,w; };
int n,m;
bitset <N> vis;
bitset <M> is;
vector <Edge> Tree[N];

inline int getSize(int u,int from)
{
    if(vis[u]) return 0;
    int tot = 1;
    for(auto E : Tree[u])
        if(E.v != from) tot += getSize(E.v,u);
    return tot;
}

int getRoot(int u,int from,int tot,int &root)
{
    if(vis[u]) return 0;

    int res = 1,mx = 0;
    for(auto E : Tree[u])
    {
        if(E.v == from) continue;
        int subSize = getRoot(E.v,u,tot,root);
        mx = max(mx,subSize),res += subSize;
    }
    mx = max(mx,tot - res);
    if(mx <= tot / 2) root = u;
    return res;

}

void getDist(int u,int from,int dist,vector <int> &v)
{
    if(vis[u]) return ;
    v.push_back(dist);
    for(auto E : Tree[u])
        if(E.v != from)
            getDist(E.v,u,dist + E.w,v);
}

void create(int u)
{
    if(vis[u]) return ;
    getRoot(u,-1,getSize(u,-1),u);
    vis[u] = 1;

    vector <vector <int>> v; v.clear();
    for(auto E : Tree[u])
    {
        v.push_back(vector <int> ());
        getDist(E.v,-1,E.w,v.back());
    }

    for(int i = 0;i < v.size();i++)
    {
        for(int j = i + 1;j < v.size();j++)
            for(int n1 : v[i]) for(int n2 : v[j])
                if(n1 + n2 < M) is[n1 + n2] = 1;
        for(int num : v[i]) if(num < M) is[num] = 1;
    }

    for(auto E : Tree[u])
        create(E.v);
}

int main()
{
    n = input(),m = input();
    for(int i = 1,u,v,w;i < n;i++)
    {
        u = input(),v = input(),w = input();
        Tree[u].push_back({v,w}),Tree[v].push_back({u,w});
    }

    create(1);

    while(m--)
        puts(is[input()] ? "AYE" : "NAY");
}

这里我有点不理解。我计算合法答案的那几行相当于枚举了一颗子树内的所有点对,复杂度至少也是 n^2 级别的,但是却过了,求解答


by Super_Cube @ 2024-10-18 21:12:32

@_WHITENIGHT 我认为您的复杂度确实假了,能过只是数据水或者洛谷神机跑得快。


by _WHITE_NIGHT_ @ 2024-10-18 21:22:49

@Super_Cube 那确实……鞭策洛谷加强数据!!!


by Super_Cube @ 2024-10-18 21:31:19

@_WHITENIGHT n10^4,当然可过。你造个 n=10^5 的菊花就死了。


by _WHITE_NIGHT_ @ 2024-10-19 14:56:30

@Super_Cube 但是1e4 n^2 还带个 log,感觉纯纯是因为洛谷数据随机构造,没有给能跑满 n ^ 2 的数据


by Super_Cube @ 2024-10-19 14:58:32

@_WHITENIGHT 大概吧。


by _WHITE_NIGHT_ @ 2024-10-19 15:04:32

@Super_Cube Thanks♪(・ω・)ノ
感谢


|