P2633 Count on a tree

一道题水一天,玄学玄学
对拍输出数据都对。。结果一直报re。。最后发现居然是因为一个没有返回值的函数没有用void类型,格式不规范开o2居然会报re?
这神仙bug谁顶得住啊
以后再遇到找不到的bug还是尽早重写吧。。。

主席树,儿子继承父亲,可以发现每个节点当前版本的权值线段树维护的就是从这一节点到根节点的权值。
于是只要倍增找到x,y两节点的lca,就可以得到:

val_tree(x ~ y) = val_tree(1 ~ x) + val_tree(1 ~ y) - val_tree(1 ~ lca) - val_tree(1 ~ fa[lca])

ac代码:

#include<bits/stdc++.h>
#define ls ls_[i]
#define rs rs_[i]
#define mid (l+r)/2
#define fill_in freopen("in.txt","r",stdin);
#define fill_out freopen("out.txt","w",stdout);
using namespace std;
typedef long long ll;
ll n,m,k,x,y,z,q,W,T,N,S,op,cnt,tmp,dst,cas,sum,val,tot,idx,test;

const int NN=200100;

vector<int> ve[NN];
int has[NN],has_size;
int a[NN],fa[NN][25],dep[NN];
int c[NN*40],ls_[NN*40],rs_[NN*40],rot[NN];

void get_hash(){
    for(int i=1;i<=n;i++) a[i]=lower_bound(has+1,has+has_size+1,a[i])-has;
    N=has_size+5;
}

void update(int l,int r,int pos,int &i,int i_){
    i=++tot;
    c[i]=c[i_]+1;
    ls=ls_[i_],rs=rs_[i_];
    if(l==r) return;
    if(mid>=pos) update(l,mid,pos,ls,ls_[i_]);
    else update(mid+1,r,pos,rs,rs_[i_]);
}

//就是这里,不小心用了int,玄学报错
void dfs(int u,int f){
    fa[u][0]=f;dep[u]=dep[f]+1;
    update(0,N,a[u],rot[u],rot[f]);
    for(int v:ve[u]) if(!dep[v]) dfs(v,u);
}

int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=20;i>=0;i--){
        int f=fa[x][i];
        if(dep[f]>=dep[y]) x=f;
    }
    if(x==y) return x;
    for(int i=20;i>=0;i--){
        int fx=fa[x][i],fy=fa[y][i];
        if(fx!=fy) x=fx,y=fy;
    }
    return fa[x][0];
}

int get_kth(int l,int r,int k,int x,int y,int f,int ff){
    if(l==r) return l;
    int c_ls=c[ls_[x]]+c[ls_[y]]-c[ls_[f]]-c[ls_[ff]];
    if(c_ls>=k) return get_kth(l,mid,k,ls_[x],ls_[y],ls_[f],ls_[ff]);
    return get_kth(mid+1,r,k-c_ls,rs_[x],rs_[y],rs_[f],rs_[ff]);
}

int main(){
    //fill_in;fill_out;
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        has[++has_size]=a[i];
    }
    sort(has+1,has+has_size+1);
    get_hash();
    for(int i=1;i<n;i++){
        cin>>x>>y;
        ve[x].push_back(y);
        ve[y].push_back(x);
    }
    dfs(1,0);
    for(int i=1;i<=20;i++){
        for(int j=1;j<=n;j++){
            fa[j][i]=fa[fa[j][i-1]][i-1];
        }
    }
    int last=0;
    for(int i=1;i<=m;i++){
        cin>>x>>y>>k;
        x^=last;
        int f=lca(x,y),ff=fa[f][0];
        last=has[get_kth(0,N,k,rot[x],rot[y],rot[f],rot[ff])];
        cout<<last<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值