• bzoj2588 Spoj10628. count on a tree


    题目描述

    给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

    输入输出格式

    输入格式:

    第一行两个整数N,M。

    第二行有N个整数,其中第i个整数表示点i的权值。

    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。

    最后M行每行两个整数(u,v,k),表示一组询问。

    输出格式:

    M行,表示每个询问的答案。

    输入输出样例

    输入样例#1:
    8 5
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5 1
    0 5 2
    10 5 3
    11 5 4
    110 8 2
    输出样例#1:
    2
    8
    9
    105
    7

    说明

    HINT:

    N,M<=100000

    暴力自重。。。

    题解

    其实就是个很简单的主席树,只要把在序列上的建树改成在树上建就可以了

    虽然我也是今天看到这道题看完题解才知道怎么在树上建主席树

    关于路径,可以在树上差分一下用$sum[l]+sum[r]-sum[lca]-sum[lca_fa]$

    然后因为要求lca,所以在树剖dfs的时候顺便建一下主席树就好了

    具体实现请参考代码

     1 //minamoto
     2 #include<bits/stdc++.h>
     3 #define N 100005
     4 #define M 2000005
     5 using namespace std;
     6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     7 char buf[1<<21],*p1=buf,*p2=buf;
     8 inline int read(){
     9     #define num ch-'0'
    10     char ch;bool flag=0;int res;
    11     while(!isdigit(ch=getc()))
    12     (ch=='-')&&(flag=true);
    13     for(res=num;isdigit(ch=getc());res=res*10+num);
    14     (flag)&&(res=-res);
    15     #undef num
    16     return res;
    17 }
    18 int sum[M],L[M],R[M];
    19 int a[N],b[N],rt[N];
    20 int fa[N],sz[N],d[N],ver[N<<1],Next[N<<1],head[N],son[N],top[N];
    21 int n,q,m,cnt=0,tot=0,ans=0;
    22 void update(int last,int &now,int l,int r,int x){
    23     sum[now=++cnt]=sum[last]+1;
    24     if(l==r) return;
    25     int mid=(l+r)>>1;
    26     if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
    27     else L[now]=L[last],update(R[last],R[now],mid+1,r,x);
    28 }
    29 inline void add(int u,int v){
    30     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
    31     ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
    32 }
    33 void dfs(int u){
    34     sz[u]=1,d[u]=d[fa[u]]+1;
    35     update(rt[fa[u]],rt[u],1,m,a[u]);
    36     for(int i=head[u];i;i=Next[i]){
    37         int v=ver[i];
    38         if(v==fa[u]) continue;
    39         fa[v]=u,dfs(v);
    40         sz[u]+=sz[v];
    41         if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
    42     }
    43 }
    44 void dfs(int u,int tp){
    45     top[u]=tp;
    46     if(!son[u]) return;
    47     dfs(son[u],tp);
    48     for(int i=head[u];i;i=Next[i]){
    49         int v=ver[i];
    50         if(v==son[u]||v==fa[u]) continue;
    51         dfs(v,v);
    52     }
    53 }
    54 int LCA(int x,int y){
    55     while(top[x]!=top[y])
    56     d[top[x]]>=d[top[y]]?x=fa[top[x]]:y=fa[top[y]];
    57     return d[x]>=d[y]?y:x;
    58 }
    59 int query(int ql,int qr,int lca,int lca_fa,int l,int r,int k){
    60     if(l>=r) return l;
    61     int x=sum[L[ql]]+sum[L[qr]]-sum[L[lca]]-sum[L[lca_fa]];
    62     int mid=(l+r)>>1;
    63     if(x>=k) return query(L[ql],L[qr],L[lca],L[lca_fa],l,mid,k);
    64     else return query(R[ql],R[qr],R[lca],R[lca_fa],mid+1,r,k-x);
    65 }
    66 int main(){
    67     //freopen("testdata.in","r",stdin);
    68     n=read(),q=read();
    69     for(int i=1;i<=n;++i)
    70     b[i]=a[i]=read();
    71     sort(b+1,b+1+n);
    72     m=unique(b+1,b+1+n)-b-1;
    73     for(int i=1;i<=n;++i)
    74     a[i]=lower_bound(b+1,b+1+m,a[i])-b;
    75     for(int i=1;i<n;++i){
    76         int u=read(),v=read();
    77         add(u,v);
    78     }
    79     dfs(1),dfs(1,1);
    80     while(q--){
    81         int x,y,z,lca;
    82         x=read(),y=read(),z=read();
    83         x^=ans,lca=LCA(x,y);
    84         ans=b[query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,m,z)];
    85         printf("%d
    ",ans);
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    我的浏览器大战
    使用Jmeter进行HTTP接口测试
    Jmeter连接SqlServer数据库进行压力测试
    java通过JDBC链接SQLServer2012 (含1433端口打通)
    读程序写结果技巧【半转】
    book118免费下载文档方法【转】
    PJ可能会用到的动态规划选讲-学习笔记
    PJ考试可能会用到的数学思维题选讲-自学教程-自学笔记
    PJ可能会考的模拟与枚举-自学教程
    TG可能会用到的动态规划-简易自学
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9392425.html
Copyright © 2020-2023  润新知