【BZOJ3551】Peaks加强版,主席树+kruskal重构+dfs序+倍增思想
2016-05-05 22:09
302 查看
传送门
写在前面:一道调了不止一上午的题目
思路:我们先来看一下神奇的kruskal重构树
图中红色的是原图的边权,黑色的是原图上的点
这样生成的树有一些十分优美的性质:
1.二叉树(好吧这题意义不大)
2.原树与新树两点间路径上边权(点权)的最大值相等
3.子节点的边权小于等于父亲节点(大根堆)
4.原树中两点之间路径上边权的最大值等于新树上两点的LCA的点权
这些神奇的性质可以解决一些图上的连通性问题。
对于这道题来说,我们就可以kruskal一下(排序+并查集),建出这样一颗二叉树。那么我们每次处理询问的时候,只需要从x一直往权值小于等于要求长度的祖先上蹦,最终所在祖先y的子树就是我们要求的点的范围,即子树上找第k大,这个我们是可以dfs序编号后用主席树来搞一下的。
总结一下就是说,我们先对边权升序排一遍,做成一棵有根的树,然后对这棵树进行dfs重新编号,并离散化原点权(即山的高度),倍增求祖先,然后对dfs后的编号建立主席树。处理询问时我们要一直往上蹦到符合条件的祖先,用主席树寻找第k大即可
注意:
1.这里求得是第k大,也就是第siz-k+1小的数
2.离散化,重编号这里很容易把人搞晕,推荐自己先写写步骤再开始码代码,我这里是先离散化原数据再dfs编号的。
3.倍增预处理和离散化操作在init函数里
4.由于是二叉树,所以采用父亲儿子表示法比较方便
5.题意感觉不是很清晰,这里让求的是第k大的权值……所以还要记录离散化后的数所对应的原权值(ID数组)
代码:
写在前面:一道调了不止一上午的题目
思路:我们先来看一下神奇的kruskal重构树
图中红色的是原图的边权,黑色的是原图上的点
这样生成的树有一些十分优美的性质:
1.二叉树(好吧这题意义不大)
2.原树与新树两点间路径上边权(点权)的最大值相等
3.子节点的边权小于等于父亲节点(大根堆)
4.原树中两点之间路径上边权的最大值等于新树上两点的LCA的点权
这些神奇的性质可以解决一些图上的连通性问题。
对于这道题来说,我们就可以kruskal一下(排序+并查集),建出这样一颗二叉树。那么我们每次处理询问的时候,只需要从x一直往权值小于等于要求长度的祖先上蹦,最终所在祖先y的子树就是我们要求的点的范围,即子树上找第k大,这个我们是可以dfs序编号后用主席树来搞一下的。
总结一下就是说,我们先对边权升序排一遍,做成一棵有根的树,然后对这棵树进行dfs重新编号,并离散化原点权(即山的高度),倍增求祖先,然后对dfs后的编号建立主席树。处理询问时我们要一直往上蹦到符合条件的祖先,用主席树寻找第k大即可
注意:
1.这里求得是第k大,也就是第siz-k+1小的数
2.离散化,重编号这里很容易把人搞晕,推荐自己先写写步骤再开始码代码,我这里是先离散化原数据再dfs编号的。
3.倍增预处理和离散化操作在init函数里
4.由于是二叉树,所以采用父亲儿子表示法比较方便
5.题意感觉不是很清晰,这里让求的是第k大的权值……所以还要记录离散化后的数所对应的原权值(ID数组)
代码:
#include<bits/stdc++.h> #define M 100010 using namespace std; int n,m,q,lastans,cnt,tot; int ID[M],belong[M<<1],h[M<<1],fa[M<<1][21],son[M<<1][2],Ls[M<<1],Rs[M<<1]; bool vis[M<<1]; struct Elite { int u,v,w; bool operator <(const Elite other)const { return w<other.w; } }eli[M*5]; struct Chairman_tree { int ch[2],siz; }a[M*50]; struct node { int data,id; bool operator <(const node other)const { return data<other.data; } }b[M]; int in() { char ch=getchar();int t=0,f=1; while (!isdigit(ch)) ch=getchar(); while (isdigit(ch)) t=(t<<3)+(t<<1)+ch-48,ch=getchar(); return f*t; } int find(int x) { if (x!=belong[x]) belong[x]=find(belong[x]); return belong[x]; } void build(int now,int L,int R,int rt,int val) { a[rt].siz=a[now].siz+1; if (L==R) return; int mid=(L+R)>>1; if (val<=mid) a[rt].ch[1]=a[now].ch[1], a[rt].ch[0]=++cnt, build(a[now].ch[0],L,mid,a[rt].ch[0],val); else a[rt].ch[0]=a[now].ch[0], a[rt].ch[1]=++cnt, build(a[now].ch[1],mid+1,R,a[rt].ch[1],val); } int get(int begin,int end,int L,int R,int k) { if (begin==end) return end; int mid=(begin+end)>>1,t=a[a[R].ch[0]].siz-a[a[L].ch[0]].siz; if (k<=t) return get(begin,mid,a[L].ch[0],a[R].ch[0],k); else return get(mid+1,end,a[L].ch[1],a[R].ch[1],k-t); } void dfs(int x) { vis[x]=1; if (x<=n) b[++tot].data=h[x],b[tot].id=x; Ls[x]=tot; if (son[x][0]) dfs(son[x][0]); if (son[x][1]) dfs(son[x][1]); Rs[x]=tot; } void init() { for (int j=1;j<20;j++) for (int i=1;i<=cnt;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; for(int i=1;i<=n;i++) b[i].id=i,b[i].data=h[i]; sort(b+1,b+n+1); for (int i=1;i<=n;i++) ID[i]=h[b[i].id],h[b[i].id]=i; } main() { n=in();m=in();q=in(); for (int i=1;i<=n;i++) h[i]=in(); for (int i=1;i<=m;i++) eli[i].u=in(),eli[i].v=in(),eli[i].w=in(); sort(eli+1,eli+m+1); cnt=n; for (int i=1;i<=n<<1;i++) belong[i]=i; for (int i=1;i<=m;i++) { int p=find(eli[i].u),q=find(eli[i].v); if (p!=q) fa[p][0]=++cnt,fa[q][0]=cnt, belong[p]=cnt,belong[q]=cnt, son[cnt][0]=p,son[cnt][1]=q, h[cnt]=eli[i].w; } fa[cnt][0]=cnt; init(); for (int i=cnt;i>=1;i--) if (!vis[i]) dfs(i); cnt=n+1; int x,y,z; for (int i=1;i<=n;i++) build(i,1,n,i+1,b[i].data); while (q--) { if (lastans==-1) lastans=0; x=in()^lastans; y=in()^lastans; z=in()^lastans; for (int i=19;i>=0;i--) if (h[fa[x][i]]<=y) x=fa[x][i]; int sz=a[Rs[x]+1].siz-a[Ls[x]+1].siz; if (sz<z) lastans=-1; else lastans=ID[get(1,n,Ls[x]+1,Rs[x]+1,sz-z+1)]; printf("%d\n",lastans); } }
相关文章推荐
- 【干货】使用Java发送各种格式的邮件
- 二叉搜索树
- Pycharm中的scrapy安装教程
- 加油 加油
- 欧拉函数的证明
- JAXB解析xml 的XML声明
- File类
- 锚点 position
- Spring Mvc那点事---(3)Spring Mvc项目创建
- 通过key-value更改按钮的圆角
- STL之 vector 总结
- 单例模式
- 0505-NABCD模型、视频
- 【LeetCode 233】所有小于等于n的整数中,1出现的总次数,(例如111算3次)
- 自定义窗口并显示
- 重写TextField修改Placeholder
- c++primer plus 第六章习题
- java JDK的安装以及配置环境变量
- cocos2d-x安装教程
- Android JNI 本地开发接口