bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)

Description

【题目描述】同3545

Input

第一行三个数N,M,Q。

第二行N个数,第i个数为h_i

接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。

接下来Q行,每行三个数v x k,表示一组询问。v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。

Output

同3545

【思路】

Kruskal+主席树+dfs序

一个叫kruskal重构树的方法QWQ。在kruskal合并子树的时候新建一个ext结点,然后让它成为两棵子树公共的根,赋边权为权值。

新建成的树的性质:

对于一个询问,我们找到v的点权值不超过x的最小祖先,以该祖先为根的子树中所有的点与v都满足条件,然后就是在一个子树中找到第k大的问题,可以基于dfs序建主席树处理。

【代码】

  1 #include<cstdlib>
  2 #include<queue>
  3 #include<vector>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<algorithm>
  8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
  9 using namespace std;
 10
 11 typedef long long ll;
 12 const int N = 200005;
 13 const int M = 5100005;
 14 const int D = 17;
 15
 16 struct Edge {
 17     int u,v,w;
 18     bool operator < (const Edge& rhs) const {
 19         return w<rhs.w;
 20     }
 21 };
 22 struct LEdge { int v,nxt;
 23 };
 24 struct Tnode{
 25     int lc,rc,sum;
 26 }T[M];
 27
 28 ll read() {
 29     char c=getchar();
 30     ll f=1,x=0;
 31     while(!isdigit(c)) {
 32         if(c==‘-‘) f=-1; c=getchar();
 33     }
 34     while(isdigit(c))
 35         x=x*10+c-‘0‘,c=getchar();
 36     return x*f;
 37 }
 38
 39 int n,m,q,sz,tot,dfsc;
 40 int hash[N],h[N],rt[N],val[N],bin[N];
 41 int p[N],dep[N],fa[N][D],mx[N][D],L[N],R[N];
 42
 43 Edge es[N<<1]; LEdge e[N<<1];
 44 int en=-1,front[N];
 45 void adde(int u,int v)
 46 {
 47     en++; e[en].v=v; e[en].nxt=front[u]; front[u]=en;
 48 }
 49 int ifind(int u)
 50 {
 51     return u==p[u]? u: p[u]=ifind(p[u]);
 52 }
 53 void update(int l,int r,int x,int& y,int num)
 54 {
 55     T[y=++sz]=T[x];
 56     T[y].sum++;
 57     if(l>=r) return ;
 58     int mid=(l+r)>>1;
 59     if(num<=mid) update(l,mid,T[x].lc,T[y].lc,num);
 60     else update(mid+1,r,T[x].rc,T[y].rc,num);
 61 }
 62 int query(int l,int r,int a,int b,int rk)
 63 {
 64     int mid=(l+r)>>1;
 65     if(l>=r) return mid;
 66     int now=T[T[b].rc].sum-T[T[a].rc].sum;
 67     if(rk<=now) return query(mid+1,r,T[a].rc,T[b].rc,rk);
 68     else return query(l,mid,T[a].lc,T[b].lc,rk-now);
 69 }
 70 void dfs(int u)
 71 {
 72     L[u]=++dfsc;
 73     update(0,tot,rt[L[u]-1],rt[L[u]],h[u]);
 74     FOR(i,1,D-1) {
 75         fa[u][i]=fa[fa[u][i-1]][i-1];
 76         mx[u][i]=max(mx[u][i-1],mx[fa[u][i-1]][i-1]);
 77     }
 78     for(int i=front[u];i>=0;i=e[i].nxt) {
 79         int v=e[i].v;
 80         dep[v]=dep[u]+1,
 81         dfs(v);
 82     }
 83     R[u]=dfsc;
 84 }
 85 int find_root(int u,int x)
 86 {
 87     for(int i=D-1;i>=0;i--)
 88         if(fa[u][i] && mx[u][i]<=x)
 89             u=fa[u][i];
 90     return u;
 91 }
 92
 93 int main()
 94 {
 95     //reopen("in.in","r",stdin);
 96     //freopen("out.out","w",stdout);
 97
 98     memset(front,-1,sizeof(front));
 99     n=read(),m=read(),q=read();
100     FOR(i,1,n) h[i]=read(),hash[i]=h[i];
101     int u,v,w,x,k,ans=0;
102     FOR(i,1,m) {
103         u=read(),v=read(),w=read();
104         es[i]=(Edge){u,v,w};
105     }
106
107     FOR(i,1,2*n) p[i]=i;
108     sort(hash+1,hash+n+1);
109     tot=unique(hash+1,hash+n+1)-hash-1;
110     FOR(i,1,n)
111         h[i]=lower_bound(hash+1,hash+tot+1,h[i])-hash;
112
113     sort(es+1,es+m+1);
114     FOR(i,1,m) {
115         Edge e=es[i];
116         int x=ifind(e.u),y=ifind(e.v);
117         if(x!=y) {
118             int ext=++n;
119             fa[x][0]=fa[y][0]=ext;
120             mx[x][0]=mx[y][0]=e.w;
121             p[x]=p[y]=ext;
122             adde(ext,x),adde(ext,y);
123         }
124     }
125
126     dfs(n);
127
128     FOR(i,1,q) {
129         v=read(),x=read(),k=read();
130         v^=ans,x^=ans,k^=ans;
131         int root=find_root(v,x);
132         if(R[root]-L[root]+1<k) puts("-1"),ans=0;
133         else {
134             ans=query(0,tot,rt[L[root]-1],rt[R[root]],k);
135             if(!ans) puts("-1");
136             else printf("%d\n",ans=hash[ans]);
137         }
138     }
139     return 0;
140 }
时间: 2025-01-16 20:38:52

bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)的相关文章

BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树

题目大意:同3545 强制在线 3545题解传送门:http://blog.csdn.net/popoqqq/article/details/40660953 强制在线没法排序 启发式合并也就用不了了 Kruskal重构树是个挺好玩的东西 可以拿来处理一些最小生成树的边权最值问题 这里我们Kruskal连边时并不直接连边 而是新建一个节点ext 将两个点所在子树都连到ext的儿子上 比如说样例的树就建成了这样 图中红色的是原图的边权,黑色的是原图上的点 这样生成的树有一些十分优美的性质: 1.二

bzoj 3551: [ONTAK2010]Peaks加强版

Description [题目描述]同3545 Input 第一行三个数N,M,Q. 第二行N个数,第i个数为h_i 接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径. 接下来Q行,每行三个数v x k,表示一组询问.v=v xor lastans,x=x xor lastans,k=k xor lastans.如果lastans=-1则不变. Output 同3545 Sample Input Sample Output HINT [数据范围]同3545 Source

51 nod 1681 公共祖先 (主席树+dfs序)

1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完全不同了,原来的祖先可能变成了后代,后代变成的同辈…… 两个人的亲密度定义为在这两个平行宇宙有多少人一直是他们的公共祖先. 整个家族的亲密度定义为任意两个人亲密度的总和. Input 第一行一个数n(1<=n<=100000)

【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. Input

【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组. |||.我们跑出来dfs序就能在他的上面进行主席树了. IV.别忘了离散. V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是...... #include <cstdio> #include

bzoj 3545&amp;&amp;3551: [ONTAK2010]Peaks &amp;&amp;加强版 平衡树&amp;&amp;并查集合并树&amp;&amp;主席树

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Status] Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. I

BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]

传送门 题意:查询树上根节点值*子树中权值和$\le m$的最大数量 最大值是多少 求$DFS$序,然后变成区间中和$\le m$最多有几个元素,建主席树,然后权值线段树上二分就行了 $WA$:又把边表开小了..... 好吧我$zz$了有根树加无向边干什么.... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #de

bzoj 3772 精神污染 主席树+dfs序

精神污染 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 637  Solved: 177[Submit][Status][Discuss] Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海陆空交通设施发达.濑户内海沿岸气候温暖,多晴天,有日本少见的贸易良港神户港所在的神户市和曾是豪

BZOJ_1803_Spoj1487 Query on a tree III_主席树+dfs序

BZOJ_1803_Spoj1487 Query on a tree III_主席树 Description You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. I