淀粉质求助

P3806 【模板】点分治 1

Disjoint_cat @ 2022-10-03 10:01:36

不知为何,#1数据本机AC,洛谷全部RE

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=10005,K=10000005;
int n,m,U,V,W,q,siz[N],root,ma[N],LEN,t;
vector<int>to[N],dis[N],v,tr;
bool can[K],Vis[N];
int froot(int now,int fa)
{
    siz[now]=1,ma[now]=0;int t;
    for(int i=0;i<to[now].size();i++)
        if((t=to[now][i])!=fa&&!Vis[t])
        {
            froot(t,now);
            siz[now]+=siz[t],ma[now]=max(ma[now],siz[t]);
        }
    ma[now]=max(ma[now],LEN-siz[now]);
    if(ma[now]<ma[root])root=now;
}
void dfs(int now,int fa,int len,int Tr)
{
    v.push_back(len),tr.push_back(Tr);
    for(int i=0;i<to[now].size();i++)
        if((t=to[now][i])!=fa)
            dfs(t,now,len+dis[now][i],Tr);
}
void sol(int Root)
{
    v.clear(),tr.clear(),v.push_back(0),tr.push_back(0);
    for(int i=0;i<to[Root].size();i++)
        if(!Vis[t=to[Root][i]])
            dfs(t,Root,dis[Root][i],t);
    for(int i=0;i<v.size();i++)
        for(int j=i+1;j<v.size();j++)
            if(tr[i]!=tr[j])can[v[i]+v[j]]=1;
}
void dfz(int Root)
{
    Vis[Root]=1;
    sol(Root);
    for(int i=0;i<to[Root].size();i++)
        if(!Vis[t=to[Root][i]])
        {
            //sol(t);
            LEN=siz[t],root=0;
            froot(t,0);
            dfz(root);
        }
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<n;i++)
    {
        cin>>U>>V>>W;
        to[U].push_back(V),to[V].push_back(U),dis[U].\
        push_back(W),dis[V].push_back(W);
    }
    LEN=n,ma[0]=n,root=0;froot(1,0);
    dfz(root);
    while(m--)
    {
        cin>>q;
        puts(can[q]?"AYE":"NAY");
    }
    return 0;
}

by Disjoint_cat @ 2022-10-03 10:02:25

Runtime Error. Received signal 11: Segmentation fault with invalid memory reference.


by Terrysong @ 2022-10-03 10:10:41

数组开小了或是引用到负数分段了


by Disjoint_cat @ 2022-10-03 10:12:21

最奇怪的是,本机测试#1是AC的,但是洛谷全部RE掉了


by RabbieWjy @ 2022-10-03 10:12:37

for(int i=0;i<v.size();i++)
    for(int j=i+1;j<v.size();j++)
        if(tr[i]!=tr[j])can[v[i]+v[j]]=1;

这一段的 can 是否会超?


by Disjoint_cat @ 2022-10-03 10:14:11

加了限制,甚至把K加到10^8试过了,但还是RE


by ABookCD @ 2022-10-03 10:14:36

https://www.luogu.com.cn/discuss/188596

++


by RabbieWjy @ 2022-10-03 10:40:02

void dfs(int now,int fa,int len,int Tr)
{
    v.push_back(len),tr.push_back(Tr);
    for(int i=0;i<to[now].size();i++)
        if((t=to[now][i])!=fa)
            dfs(t,now,len+dis[now][i],Tr);
}
void sol(int Root)
{
    v.clear(),tr.clear(),v.push_back(0),tr.push_back(0);
    for(int i=0;i<to[Root].size();i++)
        if(!Vis[t=to[Root][i]])
            dfs(t,Root,dis[Root][i],t);
    for(int i=0;i<v.size();i++)
        for(int j=i+1;j<v.size();j++)
            if(tr[i]!=tr[j])can[v[i]+v[j]]=1;
}

这里的 dfs 是否会往回走?


by 2017gdgzoi999 @ 2022-10-03 10:46:22

说一些和 RE 不相关的吧(

这个 sol 函数复杂度是 \text{O}(n^2)(因为有二层循环)所以时间总复杂度是 \text{O}(n^2logn) 就算不 RE 也会 TLE

对于每次 sol,先设置一个只有 0 的集合,每次到一个子树时第一步先对于子树的每个点 v(设当前树重心到 v 的路程为 l_v,),枚举询问 q_i,若 q_i-l_v 在集合内,则第 i 个询问有解。第二步将该子树的所有 l_v 加入集合。 // 集合元素只存到 10^7 所以用数组+时间戳实现就好了

这样应该可以优化到 \text{O}(nmlog_n)


|