zoukankan      html  css  js  c++  java
  • bzoj2588 -- 树链剖分+主席树

    先将权值离散。

    显然可以对于每个结点建一棵权值线段树存这个点到根结点的路径上的点权,询问时在线段树上二分,但这样时间是O(n2log2n)的。

    然后想到用主席树优化,时间复杂度O(n*log2n)。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 using namespace std;
     7 #define ll long long
     8 inline char nc(){
     9     static char buf[100000],*p1=buf,*p2=buf;
    10     if(p1==p2){
    11         p2=(p1=buf)+fread(buf,1,100000,stdin);
    12         if(p1==p2)return EOF;
    13     }
    14     return *p1++;
    15 }
    16 inline void Read(int& x){
    17     char c=nc(),b=1;
    18     for(;c<'0'||c>'9';c=nc())if(c=='-')b=-1;
    19     for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());x*=b;
    20 }
    21 char S[30];
    22 int Len;
    23 inline void Print(int x){
    24     for(Len=0;x;x/=10)S[++Len]=x%10;
    25     while(Len)putchar(S[Len--]+48);
    26 }
    27 #define N 100010
    28 vector<int>g[N];
    29 struct Ls{
    30     int w,f;
    31 }l[N];
    32 struct Node{
    33     int l,r,s;
    34 }c[N*80];
    35 int Ans,i,j,k,n,m,x,y,a[N],Top[N],Rt[N],f[N],d[N],s[N],Son[N],w[N],Num,Cnt,L;
    36 inline void Dfs1(int x,int F){
    37     f[x]=F;d[x]=d[F]+1;s[x]=1;
    38     for(int i=0;i<g[x].size();i++)
    39     if(g[x][i]!=F){
    40         Dfs1(g[x][i],x);
    41         if(s[g[x][i]]>s[Son[x]])Son[x]=g[x][i];
    42         s[x]+=s[g[x][i]];
    43     }
    44 }
    45 inline void Insert(int Last,int& x,int l,int r,int y){
    46     c[++Cnt]=c[Last];
    47     x=Cnt;c[x].s++;
    48     if(l==r)return;
    49     int Mid=l+r>>1;
    50     if(Mid>=y)Insert(c[Last].l,c[x].l,l,Mid,y);else Insert(c[Last].r,c[x].r,Mid+1,r,y);
    51 }
    52 inline void Dfs2(int x,int Tmp){
    53     Top[x]=Tmp;Insert(Rt[f[x]],Rt[x],1,Num,a[x]);
    54     if(Son[x])Dfs2(Son[x],Tmp);
    55     for(int i=0;i<g[x].size();i++)
    56     if(g[x][i]!=f[x]&&g[x][i]!=Son[x])Dfs2(g[x][i],g[x][i]);
    57 }
    58 inline bool Cmp(Ls a,Ls b){return a.w<b.w;}
    59 inline int Lca(int x,int y){
    60     while(Top[x]!=Top[y])
    61     if(d[Top[x]]>d[Top[y]])x=f[Top[x]];else y=f[Top[y]];
    62     return d[x]>d[y]?y:x;
    63 }
    64 inline int Query(int x,int y,int z,int p,int l,int r,int k){
    65     if(l==r)return l;
    66     int Mid=l+r>>1;
    67     int S=k-c[c[x].l].s-c[c[y].l].s+c[c[z].l].s+c[c[p].l].s;
    68     if(S<=0)return Query(c[x].l,c[y].l,c[z].l,c[p].l,l,Mid,k);
    69     return Query(c[x].r,c[y].r,c[z].r,c[p].r,Mid+1,r,S);
    70 }
    71 int main(){
    72     Read(n);Read(m);
    73     for(i=1;i<=n;i++)Read(l[i].w),l[i].f=i;
    74     sort(l+1,l+n+1,Cmp);
    75     a[l[1].f]=Num=1;w[1]=l[1].w;
    76     for(i=2;i<=n;i++)
    77     if(l[i].w==l[i-1].w)a[l[i].f]=Num;else a[l[i].f]=++Num,w[Num]=l[i].w;
    78     for(i=1;i<n;i++)Read(x),Read(y),g[x].push_back(y),g[y].push_back(x);
    79     Dfs1(1,0);Dfs2(1,1);
    80     while(m--){
    81         Read(x);Read(y);Read(k);
    82         x^=Ans;
    83         L=Lca(x,y);
    84         Ans=w[Query(Rt[x],Rt[y],Rt[L],Rt[f[L]],1,Num,k)];
    85         Print(Ans);
    86         if(m)putchar('
    ');
    87     }
    88     return 0;
    89 }
    bzoj2588
  • 相关阅读:
    C#中的委托,匿名方法和Lambda表达式
    Java 8 Lambda表达式探险
    Lambda表达式有何用处?如何使用?
    有参数的程序,可以被调用
    怎样用VB编写.DLL动态链接库文件
    Oracle 存储过程包
    EB(存储单位)
    排序之快速排序(上)
    排序之冒泡排序
    排序之堆排序
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6808373.html
Copyright © 2011-2022 走看看