树剖 dfs部分神奇RE

P3038 [USACO11DEC] Grass Planting G

yinhee @ 2022-07-15 06:46:19

rt,对着洛谷板子改过,基本上没区别,但是在第一次dfs的时候就re。求调

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<queue>
#define run int T;scanf("%d",&T);while(T--)solve
#define lb lower_bound
using namespace std;
typedef long long ll;
const int maxn=2e5+7,inf=2147483647;
const int mod=1;
int n,m,e[maxn<<2],tag[maxn<<2];
int siz[maxn],wt[maxn],dep[maxn],fa[maxn];
int cnt,dfn[maxn],rk[maxn],top[maxn];
int tot,head[maxn];
int x,y,z,ans;
bool vis[maxn];
struct node{
    int to,nxt;
}edge[maxn];
void add(int u,int v){
    edge[++tot]={v,head[u]};
    head[u]=tot;
}
void dfs1(int now){
//  return;
    siz[now]=1;
    for(int i=head[now];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v!=fa[now]){
            fa[v]=now;
            dep[v]=dep[now]+1;
            dfs1(v);
            siz[now]+=siz[v];
            if(siz[v]>=siz[wt[now]])wt[now]=v;
        }
    }
}
void dfs2(int now,int t){
    dfn[now]=++cnt;
    rk[cnt]=now;
    top[now]=t;
    if(!wt[now])return;
    dfs2(wt[now],t);
    for(int i=head[now];i;i=edge[i].nxt){
        int v=edge[i].to;
        if(v!=fa[now]&&v!=wt[now])dfs2(v,v);
    }
}
inline void pushup(int now){e[now]=e[now<<1]+e[now<<1|1];}
inline void pushdown(int l,int r,int now){
    if(!tag[now])return;
    int mid=l+r>>1;
    tag[now<<1]+=tag[now];tag[now<<1|1]+=tag[now];
    e[now<<1]+=(mid-l+1)*tag[now];e[now<<1|1]+=(r-mid)*tag[now];
    tag[now]=0;
}
void update(int l,int r,int now){
    if(l>=x&&r<=y){
        e[now]+=r-l+1;
        tag[now]++;
        return;
    }
    pushdown(l,r,now);
    int mid=l+r>>1;
    if(x<=mid)update(l,mid,now<<1);
    if(y>mid)update(mid+1,r,now<<1|1);
    pushup(now);
}
void query(int l,int r,int now){
    if(l>=x&&r<=y){
        ans+=e[now];
        return;
    }
    pushdown(l,r,now);
    int mid=l+r>>1;
    if(x<=mid)query(l,mid,now<<1);
    if(y>mid)query(mid+1,r,now<<1|1);
}
void change(int l,int r){
//  cout<<top[l]<<top[r]<<endl;
    while(top[l]!=top[r]){
        if(dep[top[l]]<dep[top[r]])swap(l,r);
        x=dfn[top[l]]-1,y=dfn[l]-1;
        update(1,n,1);
        l=fa[top[l]];
    }
    if(dep[l]>dep[r])swap(l,r);
    x=dfn[l],y=dfn[r]-1;
    update(1,n,1);
}
void ask(int l,int r){
    while(top[l]!=top[r]){
        if(dep[top[l]]<dep[top[r]])swap(l,r);
        x=dfn[top[l]]-1,y=dfn[l]-1;
        query(1,n,1);
        l=fa[top[l]];
    }
//  cout<<l<<r<<endl;
    if(dep[l]>dep[r])swap(l,r);
    x=dfn[l],y=dfn[r]-1;
    query(1,n,1);
}
signed main(){
//  freopen("P3038_4.in","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1,u,v;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    dep[1]=1;
    dfs1(1);dfs2(1,1);
    for(int i=1;i<=m;i++){
        char op=getchar();
        while(op!='P'&&op!='Q')op=getchar();
        scanf("%d%d",&x,&y);
        if(op=='Q'){
            ans=0;
            ask(x,y);
            printf("%d\n",ans);
        }else{
            change(x,y);
        }
    }
}

请忽略我看错题把单点查询打成区间查询


by bamboo12345 @ 2022-07-15 07:01:44

@yinhee 您确定是dfs的问题吗?


by yinhee @ 2022-07-15 07:02:39

@bamboo123 是的,进到第一次dfs之后就挂掉了


by bamboo12345 @ 2022-07-15 07:09:04

@yinhee 您可以输出一下节点编号试一下


by yinhee @ 2022-07-15 07:12:10

跑了第4个点的数据,到3625就挂掉了


by yinhee @ 2022-07-15 07:12:38

单独把dfs1拿出来,开1e7都挂


by bamboo12345 @ 2022-07-15 07:13:21

@yinhee 有没有可能爆栈了?


by yinhee @ 2022-07-15 07:14:46

是有可能,但是也不至于吧……总之就是特别奇怪


by yinhee @ 2022-07-15 07:17:45

@bamboo123 那请问怎么处理?


by wisdua @ 2022-07-15 07:57:43

@yinhee 你没有在dfs1的开头将fa[now]赋值!!


by Mikefeng @ 2022-07-15 08:00:05

如果用命令行调试的话,可以试着加上无限栈


| 下一页