[bzoj3545+3551][ONTAK2010]Peaks&&加强版(离线+线段树合并)||(kruskal重构树&&dfs序+主席树)
2017-10-27 18:10
543 查看
传送门
没权限号可以来这里交,老规矩,不准说。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。
1 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2
1
-1
8
N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
我们把边按权值排序,然后不断加入边,处理询问,加边的时候可以启发式合并。
然后时间复杂度就是O(nlog2n)了。
然后就有了另一个题:bzoj3551 peaks加强版(强制在线)
这个我也是才学,不会讲,还是放po姐的博客吧:
http://blog.csdn.net/PoPoQQQ/article/details/41348785
那个图就是样例输入的重构树,大家可以自己模拟一下它是如何建出来的。
还有,那几个性质好好想一想。
然后应该就懂了,po姐还是讲得很好的。
过程:
1.读入
2.离散化
3.做kruskal,同时构造出重构树
4.在kruskal重构树上dfs一遍,然后找出dfs序(只有叶子)和每个节点的子树中的叶子数量,以及每个点的子树在dfs序上的起始位置
5.在dfs序上建主席树
6.利用kruskal重构树的性质,我们只需要在dfs时处理出来每个点向上跳2^j步的位置,然后倍增地去跳到权值<=限制权值的深度最小的点,它的子树就是限制下可以到达的所有节点。
7.对于查询,我们在主席树上利用之前的信息直接查询即可。
跑得好慢
分别是9632ms(3545),17124ms(3551)
都是卡线呀(滑稽)
代码:
没权限号可以来这里交,老规矩,不准说。
题面
Description
在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。Input
第一行三个数N,M,Q。第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。
Output
对于每组询问,输出一个整数表示答案。Sample Input
10 11 41 2 3 4 5 6 7 8 9 10
1 4 4
2 5 3
9 8 2
7 8 10
7 1 4
6 7 1
6 4 8
2 1 5
10 8 10
3 4 7
3 4 6
1 5 2
1 5 6
1 5 8
8 9 2
Sample Output
61
-1
8
HINT
【数据范围】N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。
题解
首先,这个题有一个比较明显的做法,就是离线处理。我们把边按权值排序,然后不断加入边,处理询问,加边的时候可以启发式合并。
然后时间复杂度就是O(nlog2n)了。
然后就有了另一个题:bzoj3551 peaks加强版(强制在线)
这个我也是才学,不会讲,还是放po姐的博客吧:
http://blog.csdn.net/PoPoQQQ/article/details/41348785
那个图就是样例输入的重构树,大家可以自己模拟一下它是如何建出来的。
还有,那几个性质好好想一想。
然后应该就懂了,po姐还是讲得很好的。
过程:
1.读入
2.离散化
3.做kruskal,同时构造出重构树
4.在kruskal重构树上dfs一遍,然后找出dfs序(只有叶子)和每个节点的子树中的叶子数量,以及每个点的子树在dfs序上的起始位置
5.在dfs序上建主席树
6.利用kruskal重构树的性质,我们只需要在dfs时处理出来每个点向上跳2^j步的位置,然后倍增地去跳到权值<=限制权值的深度最小的点,它的子树就是限制下可以到达的所有节点。
7.对于查询,我们在主席树上利用之前的信息直接查询即可。
跑得好慢
分别是9632ms(3545),17124ms(3551)
都是卡线呀(滑稽)
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<cstdlib> #include<vector> #include<queue> #define ll long long using namespace std; inline int read(){ int x=0,f=1;char ch=' '; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')f=-1,ch=getchar(); while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-48,ch=getchar(); return x*f; } const int N=1e5+500; const int M=5e5+500; struct kedge{ int x,y,l; inline bool operator < (const kedge& b) const {return l<b.l;} }e[M]; struct edge{ int to,next; }e1[M<<1],e2[M+N]; int n,m,q,tot1,tot2,tot,hash_cnt; int h ,fa[N+M],head1 ,head2[N+M],w[N+M],dep[N+M],b ; inline void addedge1(int x,int y){e1[++tot1].to=y;e1[tot1].next=head1[x];head1[x]=tot1;} inline void addedge2(int x,int y){e2[++tot2].to=y;e2[tot2].next=head2[x];head2[x]=tot2;} inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} inline void kruskal(){ for(int i=1;i<=n;i++)fa[i]=i,w[i]=h[i]; sort(e+1,e+m+1);tot=n;int j=n; for(int i=1;i<=m;i++){ int x=e[i].x;int y=e[i].y;int l=e[i].l; int u=find(x);int v=find(y); if(u==v)continue; w[++tot]=l; addedge2(tot,u);addedge2(tot,v); fa[u]=fa[v]=fa[tot]=tot; j--;if(j==1)break; } } struct node{ int ls,rs,size; }t[N*25]; int st[20][N+M],size[N+M],dfn[N+M],dfn_clock,cnt,root[N+M],mp[N+M],start[N+M]; inline void dfs(int x){ for(int k=1;k<=19&&(1<<k)<=dep[x];k++){ st[k][x]=st[k-1][st[k-1][x]]; } size[x]=0;start[x]=dfn_clock+1; if(x<=n)dfn[++dfn_clock]=x,size[x]++,mp[x]=dfn_clock; for(int i=head2[x];i;i=e2[i].next){ int u=e2[i].to; st[0][u]=x;dep[u]=dep[x]+1; dfs(u); size[x]+=size[u]; } } inline void build(int &now,int l,int r){ now=++cnt; if(l==r)return; int mid=(l+r)>>1; build(t[now].ls,l,mid); build(t[now].rs,mid+1,r); } inline void insert(int &now,int pre,int l,int r,int x){ now=++cnt; t[now]=t[pre]; t[now].size++; if(l==r)return; int mid=(l+r)>>1; if(x<=mid)insert(t[now].ls,t[pre].ls,l,mid,x); else insert(t[now].rs,t[pre].rs,mid+1,r,x); } inline int kth(int now,int pre,int l,int r,int k){ if(l==r){ if(k>t[now].size-t[pre].size)return -1; else return b[l]; } int rsize=t[t[now].rs].size-t[t[pre].rs].size; int mid=(l+r)>>1; if(k<=rsize)return kth(t[now].rs,t[pre].rs,mid+1,r,k); else return kth(t[now].ls,t[pre].ls,l,mid,k-rsize); } inline void make(){ build(root[0],1,hash_cnt); for(int i=1;i<=dfn_clock;i++){ h[dfn[i]]=lower_bound(b+1,b+hash_cnt+1,h[dfn[i]])-b; insert(root[i],root[i-1],1,hash_cnt,h[dfn[i]]); } } inline int jump(int x,int V){ for(int k=19;k>=0;k--){ if(st[k][x]&&w[st[k][x]]<=V){ x=st[k][x]; } } return x; } int main(){ n=read();m=read();q=read(); for(int i=1;i<=n;i++)h[i]=read(),b[i]=h[i]; sort(b+1,b+n+1); hash_cnt=unique(b+1,b+n+1)-b-1; for(int i=1;i<=m;i++){ int x=read(),y=read(),l=read(); addedge1(x,y);addedge1(y,x); e[i].x=x;e[i].y=y;e[i].l=l; } kruskal(); dep[tot]=1; dfs(tot); make(); int lastans=0; while(q--){ int x=read()^lastans,V=read()^lastans,k=read()^lastans; int top=jump(x,V); lastans=kth(root[start[top]+size[top]-1],root[start[top]-1],1,hash_cnt,k); printf("%d\n",lastans); if(lastans==-1)lastans=0; } return 0; }
相关文章推荐
- bzoj3545&&3551: [ONTAK2010]Peaks离线&&在线【线段树合并&&kruskal重构树&&主席树】
- BZOJ 3551: [ONTAK2010]Peaks加强版 [Kruskal重构树 dfs序 主席树]
- [主席树 Kruscal] BZOJ 3545 [ONTAK2010]Peaks & 3551 [ONTAK2010]Peaks加强版
- 【BZOJ 3545】【ONTAK 2010】Peaks & 【BZOJ 3551】【ONTAK 2010】Peaks加强版 Kruskal重构树
- bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- [BZOJ3551][ONTAK2010]Peaks(加强版)(Kruskal重构树,主席树)
- bzoj3545 [ONTAK2010]Peaks(离线+kruskal+主席树+线段树合并)
- bzoj3551 [ONTAK2010]Peaks加强版(kruskal重构树+dfs序+主席树+树上倍增)
- BZOJ 3551 ONTAK2010 Peaks加强版 Kruskal重构树+可持久化线段树
- 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树
- bzoj3551 [ONTAK2010]Peaks加强版(Kruskal重构树+主席树)
- 【BZOJ3551】[ONTAK2010]Peaks加强版 最小生成树+DFS序+主席树
- 【BZOJ-3545&3551】Peaks&加强版 Kruskal重构树 + 主席树 + DFS序 + 倍增
- bzoj 3551: [ONTAK2010]Peaks加强版 Kruskal重构树+可持久化线段树
- 3551: [ONTAK2010]Peaks加强版 kruskal重构树+dfs序+主席树
- 【bzoj3551】【ONTAK2010】【peaks加强版】【主席树】
- bzoj 3545: [ONTAK2010]Peaks 线段树合并
- [bzoj3445][ONTAK2010]Peaks 离线+线段树合并