[BZOJ2588][SPOJ10628]Count on a tree

题目大意:
  给定一棵$n(n\leq100000)$个结点的带点权的树,有$m(m\leq100000)$组询问,每次询问$u$到$v$的路径上第$k$小的权值。强制在线。

思路:
  每个结点根据父结点建立可持久化权值线段树,查询时就查询$u+v-lca(u,v)-par[lca(u,v)]$的树即可。

  1 #include<list>
  2 #include<cstdio>
  3 #include<cctype>
  4 #include<algorithm>
  5 inline int getint() {
  6     register char ch;
  7     while(!isdigit(ch=getchar()));
  8     register int x=ch^'0';
  9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 10     return x;
 11 }
 12 const int N=100001,M=100000,logN=17;
 13 int w[N],tmp[N],dep[N],anc[N][logN];
 14 std::list<int> e[N];
 15 inline void add_edge(const int &u,const int &v) {
 16     e[u].push_back(v);
 17     e[v].push_back(u);
 18 }
 19 class FotileTree {
 20     private:
 21         struct Node {
 22             int val;
 23             Node *left,*right;
 24             Node() {}
 25             Node(const Node *const &p) {
 26                 *this=*p;
 27             }
 28         };
 29     public:
 30         Node *root[N];
 31         FotileTree() {
 32             root[0]=new Node;
 33             root[0]->left=root[0]->right=root[0];
 34         }
 35         Node *modify(const Node *const &last,const int &b,const int &e,const int &x) {
 36             Node *const p=new Node(last);
 37             p->val++;
 38             if(b==e) return p;
 39             const int mid=(b+e)>>1;
 40             if(x<=mid) p->left=modify(last->left,b,mid,x);
 41             if(x>mid) p->right=modify(last->right,mid+1,e,x);
 42             return p;
 43         }
 44         int query(const Node *const &p1,const Node *const &p2,const Node *const &p3,const Node *const &p4,const int &b,const int &e,const int &k) {
 45             if(b==e) return b;
 46             const int mid=(b+e)>>1;
 47             if(k<=p1->left->val+p2->left->val-p3->left->val-p4->left->val) return query(p1->left,p2->left,p3->left,p4->left,b,mid,k);
 48             return query(p1->right,p2->right,p3->right,p4->right,mid+1,e,k-(p1->left->val+p2->left->val-p3->left->val-p4->left->val));
 49         }
 50 };
 51 FotileTree t;
 52 inline int log2(const float &x) {
 53     return ((unsigned&)x>>23&255)-127;
 54 }
 55 void dfs(const int &x,const int &par) {
 56     t.root[x]=t.modify(t.root[par],1,tmp[0],w[x]);
 57     anc[x][0]=par;
 58     dep[x]=dep[par]+1;
 59     for(register int i=1;i<=log2(dep[x]);i++) {
 60         anc[x][i]=anc[anc[x][i-1]][i-1];
 61     }
 62     for(std::list<int>::iterator i=e[x].begin();i!=e[x].end();i++) {
 63         const int &y=*i;
 64         if(y==par) continue;
 65         dfs(y,x);
 66     }
 67 }
 68 inline int get_lca(int u,int v) {
 69     if(dep[u]<dep[v]) std::swap(u,v);
 70     while(dep[u]!=dep[v]) {
 71         u=anc[u][log2(dep[u]-dep[v])];
 72     }
 73     if(u==v) return u;
 74     for(register int i=log2(dep[u]);~i;i--) {
 75         if(anc[u][i]!=anc[v][i]) {
 76             u=anc[u][i];
 77             v=anc[v][i];
 78         }
 79     }
 80     return anc[u][0];
 81 }
 82 int main() {
 83     const int n=getint(),m=getint();
 84     for(register int i=1;i<=n;i++) {
 85         w[i]=tmp[i]=getint();
 86     }
 87     std::sort(&tmp[1],&tmp[n]+1);
 88     tmp[0]=std::unique(&tmp[1],&tmp[n]+1)-&tmp[1];
 89     for(register int i=1;i<=n;i++) {
 90         w[i]=std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,w[i])-&tmp[0];
 91     }
 92     for(register int i=1;i<n;i++) {
 93         add_edge(getint(),getint());
 94     }
 95     dfs(1,0);
 96     for(register int i=0,ans=0;i<m;i++) {
 97         const int u=getint()^ans,v=getint(),k=getint(),lca=get_lca(u,v);
 98         if(i) putchar('\n');
 99         printf("%d",ans=tmp[t.query(t.root[u],t.root[v],t.root[lca],t.root[anc[lca][0]],1,tmp[0],k)]);
100     }
101     return 0;
102 }

 

posted @ 2018-02-23 11:10  skylee03  阅读(133)  评论(0编辑  收藏  举报