bzoj3551 Peaks加强版
这个题……感觉离线和在线的代码难度差不多(pb_ds不要说话)。
离线的话,就是把所有询问按照w排个序,然后一边Kruskal+平衡树启发式合并一边回答询问就好了。
在线也不难写。首先Kruskal重构树(这个Kruskal重构树是不按秩合并还要添虚点的那种……),那么每个点可以到达的点一定在某个子树里。子树的dfs序是连续的,所以可以对dfs序建主席树来求区间k大。又因为只有叶子节点的点权是有意义的,所以可以只对叶子的dfs序建主席树。查询的时候倍增跳到最高的w<=询问的w的点然后主席树就好了。
其实树剖跳父亲也可以,先跳整条链,整条链跳不动的时候就在最后一条链上二分,也是O(logn)的。不过可能是太弱,二分写挂了,结果WA到死……无奈用倍增重写了一遍。
限时20s,结果我跑了19.8s,这速度真是感人肺腑……
还有,copy的那个a一开始忘了+1了,调了一节课,虚死……
/**************************************************************
Problem: 3551
User: hzoier
Language: C++
Result: Accepted
Time:19800 ms
Memory:114432 kb
****************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,maxe=;
struct edge{
int from,to,w;
bool operator<(const edge &e)const{return w<e.w;}
}e[maxe+maxn];
void Kruskal();
int findroot(int);
void mergeset(int,int);
void dfs(int);
void build(int,int,int&,int);
void query(int,int,int,int);
int sm[maxn<<],lc[maxn<<],rc[maxn<<],root[maxn],tree_cnt=;
int n,M=,m,q,h[maxn],a[maxn],cnt,prt[maxn],w[maxn],f[maxn][],ch[maxn][],L[maxn],R[maxn],pr=,x,d,k,ans;
int main(){
scanf("%d%d%d",&n,&m,&q);
while((<<M)<(n<<))M++;
for(int i=;i<=n;i++)scanf("%d",&h[i]);
copy(h+,h+n+,a+);
sort(a+,a+n+);
for(int i=;i<=n;i++)h[i]=lower_bound(a+,a+n+,h[i])-a;
for(int i=;i<=m;i++)scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w);
for(int i=;i<=n;i++){
e[++m].from=;
e[m].to=i;
e[m].w=~(<<);
}
cnt=n;
Kruskal();
dfs(cnt);
for(int j=;j<=M;j++)for(int i=;i<=cnt;i++)f[i][j]=f[f[i][j-]][j-];
while(q--){
scanf("%d%d%d",&x,&d,&k);
if(ans!=-){x^=ans;d^=ans;k^=ans;}
for(int j=M;j!=-;j--)if(f[x][j]&&w[f[x][j]]<=d)x=f[x][j];
query(,n,root[R[x]],root[L[x]-]);
printf("%d\n",ans);
}
return ;
}
void Kruskal(){
for(int i=;i<=n;i++)prt[i]=i;
stable_sort(e+,e+m+);
for(int i=;i<=m;i++)if(findroot(e[i].from)!=findroot(e[i].to)){
cnt++;
prt[cnt]=cnt;
w[cnt]=e[i].w;
ch[cnt][]=findroot(e[i].from);
ch[cnt][]=findroot(e[i].to);
mergeset(e[i].from,cnt);
mergeset(e[i].to,cnt);
}
}
int findroot(int x){return prt[x]==x?x:(prt[x]=findroot(prt[x]));}
void mergeset(int x,int y){prt[findroot(x)]=findroot(y);}
void dfs(int x){
if(ch[x][]){
f[ch[x][]][]=f[ch[x][]][]=x;
dfs(ch[x][]);
dfs(ch[x][]);
L[x]=L[ch[x][]];
R[x]=R[ch[x][]];
}
else{
k=h[x];
build(,n,root[pr+],root[pr]);
L[x]=R[x]=++pr;
}
}
void build(int l,int r,int &rt,int pr){
sm[rt=++tree_cnt]=sm[pr]+;
if(l==r)return;
lc[rt]=lc[pr];rc[rt]=rc[pr];
int mid=(l+r)>>;
if(k<=mid)build(l,mid,lc[rt],lc[pr]);
else build(mid+,r,rc[rt],rc[pr]);
}
void query(int l,int r,int rt,int pr){
if(sm[rt]-sm[pr]<k){
ans=-;
return;
}
if(l==r){
ans=a[l];
return;
}
int mid=(l+r)>>;
if(k<=sm[rc[rt]]-sm[rc[pr]])query(mid+,r,rc[rt],rc[pr]);
else{
k-=sm[rc[rt]]-sm[rc[pr]];
query(l,mid,lc[rt],lc[pr]);
}
}
尽头和开端,总有一个在等你。
bzoj3551 Peaks加强版的更多相关文章
- 2018.09.30 bzoj3551:Peaks加强版(dfs序+主席树+倍增+kruskal重构树)
传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...
- BZOJ3551 Peaks加强版 [Kruskal重构树,主席树]
BZOJ 思路 我觉得这题可持久化线段树合并也可以做 我觉得这题建出最小生成树之后动态点分治+线段树也可以做 还是学习一下Kruskal重构树吧-- Kruskal重构树,就是在做最小生成树的时候,如 ...
- 【BZOJ3551】 [ONTAK2010]Peaks加强版
BZOJ3551 [ONTAK2010]Peaks加强版 Solution Kruscal重构树后发现可以对于小于的离散化然后倍增+主席树找到上一个的可行解. 然后就可以了. 如果数组开的不好,容易在 ...
- 【BZOJ3551】Peaks加强版(Kruskal重构树,主席树)
[BZOJ3551]Peaks加强版(Kruskal重构树,主席树) 题面 BZOJ Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相 ...
- 【BZOJ3551】[ONTAK2010]Peaks加强版 最小生成树+DFS序+主席树
[BZOJ3545][ONTAK2010]Peaks Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困 ...
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
3551: [ONTAK2010]Peaks加强版 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2438 Solved: 763[Submit][ ...
- bzoj3545/bzoj3551 [ONTAK2010]Peaks/Peaks加强版
bzoj3545/bzoj3551 [ONTAK2010]Peaks/Peaks加强版 传送门:bzoj bzoj wdnmd为什么加强版不是权限题原题却是啊 3545: [ONTAK2010]Pe ...
- [BZOJ3531] Peaks加强版
Peaks Peaks 加强版 Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越 ...
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1202 Solved: 321[Submit][Sta ...
随机推荐
- jquery easy ui datagrid中遇到的坑爹的問題。。。
; //修改 function Update() { //獲取選中行 var selected = $("#dg1").datagrid('getSelected'); //判斷是 ...
- java画图之初体验
1.实现画图程序所需的API类 JFrame JButton ActionListener 动作事件接口 ActionEvent ...
- 覆盖问题:最大覆盖问题(Maximum Covering Location Problem,MCLP)和集覆盖问题(Location Set Covering Problem,LSCP)
集覆盖问题研究满足覆盖所有需求点顾客的前提下,服务站总的建站个数或建 设费用最小的问题.集覆盖问题最早是由 Roth和 Toregas等提出的,用于解决消防中心和救护车等的应急服务设施的选址问题,他们 ...
- 【JavaScript】冒泡排序,字符串排序,数字排序
原理:是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, function bubbleClick() { var str = "50,1,4,6,9,76,43,22,2, ...
- Linux任务调度进程crontab的使用方法和注意事项
参考文章:Linux任务调度进程crond命令的使用方法和注意事项 一.crond简介 概念 crond的概念和crontab是不可分割的.crontab是一个命令,常见于Unix和类Unix的操作系 ...
- git-添加公钥
安装完git后,打开开git bush 输入以下命令 git config --global user.name "Your Name" git config --global u ...
- requestAnimationFrame,Web中写动画的另一种选择
HTML5/CSS3时代,我们要在web里做动画选择其实已经很多了: 你可以用CSS3的animattion+keyframes; 你也可以用css3的transition; 你还可以用通过在canv ...
- iOS多线程的详情使用示例--简进祥
大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的,一个复杂的多步操作只能 ...
- bzoj2086【Poi2010】Blocks
因为long long还有PE的事WA了一下午TAT 考虑一段可行区间的平均值肯定>=k 也就是说将每个数减去k以后,一段可行区间的和非负,求一段最长区间. 一段区间的和肯定是两个前缀和的差 先 ...
- Leetcode 144. Binary Tree Preorder Traversal
参考例子:[8,3,1,6,4,7,10,14,13] 8,3,1 和 6,4 说明从root开始,沿着左臂向下寻找leaf 的过程中应该逐个将node.val push入ans. class Sol ...