【bzoj2588】Count on a tree

Portal -->bzoj2588

Solution

  不行我一定要来挂这道题qwq很气愤qwq(其实还不是因为自己蠢。。)

  额首先说一下正解

  如果这个问题放在序列上面的话。。直接离散化一下然后一个可持久化权值线段树就好了

  然后放在树上的话,我们可以考虑处理树上点对问题的一个很常见的套路:
\[
info(x\rightarrow y)=info(root\rightarrow x)+info(root\rightarrow y)-info(root\rightarrow lca)*2
\]
  那所以我们还是用可持久化权值线段树,每一个节点\(x\)从\(fa[x]\)更新过来就好了

  一个小trick是在查询的时候直接传参这样比较方便

?  还有就是因为是点值,所以要记得算上\(lca\)处的值

  

  好的然而我在场上想到的是这样的:

  “放在序列上直接可持久化权值线段树那放在树上当然是套个树链剖分啊”

  然后码了个线段树合并什么的qwq总共4k,然后T掉了,原因是。。貌似这题的合并还是怎么的并不是log的。。。

  

  综上,这题一定要挂上来,太气了qwq被自己蠢哭我需要智力康复qwq

  
  正解的代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define TOP 20
using namespace std;
const int N=100010,SEG=(N+20)*20;
struct xxx{
    int y,nxt;
}a[N*2];
int pre[TOP+1][N],dep[N],V[N],val[N],Lis[N];
int h[N],sz[N],son[N];
int n,m,lastans,tot,dfn_t;
namespace Seg{/*{{{*/
    int ch[SEG][2],sz[SEG],rt[N];
    int n,tot,tot1;
    void pushup(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]];}
    int newnode(int pre){
        ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1]; sz[tot]=sz[pre];
        return tot;
    }
    void _insert(int pre,int &x,int d,int lx,int rx){
        x=newnode(pre);
        if (lx==rx){++sz[x]; return;}
        int mid=lx+rx>>1;
        if (d<=mid) _insert(ch[pre][0],ch[x][0],d,lx,mid);
        else _insert(ch[pre][1],ch[x][1],d,mid+1,rx);
        pushup(x);
    }
    void insert(int pre,int x,int d){_insert(rt[pre],rt[x],d,1,n);tot1=tot;}
    int _query(int l,int r,int lca,int lx,int rx,int k,int pos){//pos=val[lca]
        if (lx==rx) return lx;
        int mid=lx+rx>>1,lsz=sz[ch[r][0]]+sz[ch[l][0]]-2*sz[ch[lca][0]];
        if (lx<=pos&&pos<=mid) ++lsz;
        if (k<=lsz) return _query(ch[l][0],ch[r][0],ch[lca][0],lx,mid,k,pos);
        return _query(ch[l][1],ch[r][1],ch[lca][1],mid+1,rx,k-lsz,pos);
    }
    int query(int l,int r,int lca,int k){return _query(rt[l],rt[r],rt[lca],1,n,k,val[lca]);}
    void _debug(int x,int l,int r){
        if (!x){
            for (int i=l;i<=r;++i) printf("%d %d\n",i,0);
            return;
        }
        if (l==r) {printf("%d %d\n",l,sz[x]);return;}
        int mid=l+r>>1;
        _debug(ch[x][0],l,mid);
        _debug(ch[x][1],mid+1,r);
    }
    void debug(int x){_debug(rt[x],1,n);}
}/*}}}*/

void add(int x,int y){a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;}

void dfs(int fa,int x,int d){
    pre[0][x]=fa; dep[x]=d;
    Seg::insert(fa,x,val[x]);
    for (int i=1;i<=TOP;++i) pre[i][x]=pre[i-1][pre[i-1][x]];
    int u;
    for (int i=h[x];i!=-1;i=a[i].nxt){
        u=a[i].y;
        if (u==fa) continue;
        dfs(x,u,d+1);
    }
}

void prework(){
    sort(Lis+1,Lis+1+n);
    Lis[0]=unique(Lis+1,Lis+1+n)-Lis-1;
    int x;
    for (int i=1;i<=n;++i){
        x=lower_bound(Lis+1,Lis+1+Lis[0],val[i])-Lis;
        V[x]=val[i];
        val[i]=x;
    }
    Seg::n=Lis[0];
}

int get_lca(int x,int y){
    if (dep[x]<dep[y]) swap(x,y);
    for (int i=TOP;i>=0;--i)
        if (dep[pre[i][x]]>=dep[y]) x=pre[i][x];
    if (x==y) return x;
    for (int i=TOP;i>=0;--i)
        if (pre[i][x]!=pre[i][y]) x=pre[i][x],y=pre[i][y];
    return pre[0][x];
}

void solve(int x,int y,int k){
    int lca=get_lca(x,y);
    /*Seg::debug(x); printf("\n");
    Seg::debug(y); printf("\n");
    Seg::debug(lca); printf("\n");*/
    lastans=Seg::query(x,y,lca,k);
    printf("%d\n",V[lastans]);
    lastans=V[lastans];
}

int main(){/*{{{*/
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
#endif
    int x,y,k;
    scanf("%d%d",&n,&m);
    memset(h,-1,sizeof(h));
    tot=0;
    for (int i=1;i<=n;++i) scanf("%d",val+i),Lis[++Lis[0]]=val[i];
    for (int i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y); add(y,x);
    }

    prework();
    dfs(0,1,1);

    lastans=0;
    for (int i=1;i<=m;++i){
        scanf("%d%d%d",&x,&y,&k);
        x^=lastans;
        solve(x,y,k);
    }
}/*}}}*/

原文地址:https://www.cnblogs.com/yoyoball/p/9309561.html

时间: 2024-10-26 14:58:56

【bzoj2588】Count on a tree的相关文章

【BZOJ-2588】Count on a tree 主席树 + 倍增

2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 3749  Solved: 873[Submit][Status][Discuss] Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行

【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA

传送门 写在前面:一天下来就写了两道主席树的题--(codevs上的一道智障天梯不算) 思路: 才知道原来主席树不仅可以通过dfs序维护子树区间,还可以直接维护一条到根的链-- 我们建好主席树后,每次查询u->v路径上的第k大,无非有两种情况 1.u,v在同一条链上 2.u,v不在同一条链上 其实这两种情况处理起来是一样的,我们利用主席树中的前缀和思路,root[u]并上root[v]再减去root[lca(u,v)]再减去root[fa[lca(u,v)]]就是u->v路径上的点了(可以自己

【BZOJ2588】Spoj 10628. Count on a tree 主席树+LCA

[BZOJ2588]Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数表示点i的权值. 后面N-1行每行两个整数(x,y),表示点x到点y有一条边. 最后M行每行两个整数(u,v,k),表示一组

【数据挖掘】分类之decision tree(转载)

[数据挖掘]分类之decision tree. 1. ID3 算法 ID3 算法是一种典型的决策树(decision tree)算法,C4.5, CART都是在其基础上发展而来.决策树的叶子节点表示类标号,非叶子节点作为属性测试条件.从树的根节点开始,将测试条件用于检验记录,根据测试结果选择恰当的分支:直至到达叶子节点,叶子节点的类标号即为该记录的类别. ID3采用信息增益(information gain)作为分裂属性的度量,最佳分裂等价于求解最大的信息增益. 信息增益=parent节点熵 -

【DataStructure】Implemantation of Binary Tree

Statements: This blog was written by me, but most of content  is quoted from book[Data Structure with Java Hubbard] Here is a class for binary trees that directly implements the recursive definition. By extending the AbstractCollectionclass, it remai

【LeetCode】Validate Binary Search Tree

Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys

【BZOJ2870】最长道路tree 点分治+树状数组

[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来往,所以每个路口i都有一个拥挤程度v[i],我们认为从路口s走到路口t的痛苦程度为s到t的路径上拥挤程度的最小值,乘上这条路径上的路口个数所得的积.现在请你求出痛苦程度最大的一条路径,你只需输出这个痛苦程度. 简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积

【HDU1325】Is It A Tree?(并查集基础题)

有以下坑点: 1.结束输入不一定-1,题目中的叙述只是说所有权值都为正值. 2.是否构成一棵树不能只判断是否只有一个根节点,没有环路,而且还需要判断每个节点的入度一定是1,不然就不是一棵树. (无环路也可用树的性质:结点数 = 边树 + 1 来取代) 1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cctype> 5 #include <cmath&

【LeetCode】Validate Binary Search Tree 解题报告

今天CSDN博客发生异常,折腾了大半天终于发出了这篇博文. [题目] Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a