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(‘\n‘);
87     }
88     return 0;
89 }

bzoj2588

时间: 2024-12-27 21:40:43

bzoj2588 -- 树链剖分+主席树的相关文章

hdu 6162 Ch’s gift(树链剖分+主席树)

题目链接:hdu 6162 Ch's gift 题意: 给你一棵树,树上每个点有一个权值,现在有m个询问,每次询问给你一个s,t,L,R,问你从s到t的路径上,权值在[L,R]内的总和为多少. 题解: 我感觉我写复杂了,用树链剖分来维护路径,然后用主席树来建立权值线段树乱搞. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=(a);i<=(b);

BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链上的第k大值 题解 水题. 就是烦了一点. 树链剖分+带修主席树. 带修主席树: BZOJ1901 Zju2112 Dynamic Rankings 主席树 代码 #include <cstring> #include <cstdio> #include <algorithm&g

BZOJ3531 SDOI2014 旅行 - 树链剖分,主席树

题意:给定一棵树,树上每个点有权值和类型.支持:修改某个点的类型:修改某个点的权值:询问某条链上某个类型的点的和/最大值.点数/类型数/询问数<=100000. 分析: 树链剖分,对每个类型的点建立线段树(动态开点). note: 忘记写t_query返回值调半天-- 莫名其妙地1A 代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int a[5000005],s[5000005],dep[100005],size[10

[BZOJ 4012][HNOI2015]开店(树链剖分+主席树)

Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非常好啦,但是她们也发现她们面临着一个问题,那就是店开在哪里,面向什么样的人群.很神奇的是,幻想乡的地图是一个树形结构,幻想乡一共有 n个地方,编号为 1 到 n,被 n-1 条带权的边连接起来.每个地方都住着一个妖怪,其中第 i 个地方的妖怪年龄是 x_i.妖怪都是些比较喜欢安静的家伙,所以它们并不希望和很多妖怪相邻.所以这

2019年ICPC南昌网络赛 J. Distance on the tree 树链剖分+主席树

边权转点权,每次遍历到下一个点,把走个这条边的权值加入主席树中即可. #include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> using namespace std; const int maxx = 2e5+10; struct node{ int l,r,cnt; }tree[maxx*40]; int head[maxx],rk[maxx],siz[maxx

Codechef FIBTREE 树链剖分 主席树 LCA 二次剩余 快速幂

原文链接https://www.cnblogs.com/zhouzhendong/p/CC-FIBTREE.html 题目传送门 - CC-FIBTREE 题意 题解 代码 #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=100005,S=N*200,mod=1e9+9; struct Gragh{ static const int M=N*2; int cnt,y[M],nxt[M

【BZOJ】1146: [CTSC2008]网络管理Network(树链剖分+线段树套平衡树+二分 / dfs序+树状数组+主席树)

第一种做法(时间太感人): 这题我真的逗了,调了一下午,疯狂造数据,始终找不到错. 后来发现自己sb了,更新那里没有打id,直接套上u了.我.... 调了一下午啊!一下午的时光啊!本来说好中午A掉去学习第二种做法,噗 好吧,现在第一种做法是hld+seg+bst+二分,常数巨大,log^4级别,目前只会这种. 树剖后仍然用线段树维护dfs序区间,然后在每个区间建一颗平衡树,我用treap,(这题找最大啊,,,囧,并且要注意,这里的rank是比他大的数量,so,我们在二分时判断要判断一个范围,即要

Aizu 2450 Do use segment tree 树链剖分+线段树

Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show.php?pid=39566 Description Given a tree with n (1 ≤ n ≤ 200,000) nodes and a list of q (1 ≤ q ≤ 100,000) queries, process the queries in order and out

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include