zoukankan      html  css  js  c++  java
  • bzoj3551 [ONTAK2010]Peaks加强版

    Description

    //【题目描述】同3545
    在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,表示一组询问。v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。 

    Output

    //同3545
    对于每组询问,输出一个整数表示答案。

    Sample Input

    Sample Output

    HINT

    //【数据范围】同3545
    N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。

    正解:$kruskal$重构树+主席树。

    这题的普通版是权限题。。

    有一个神奇的东西,叫做$kruskal$重构树。

    我们在做最小生成树的时候,并不是直接把两个联通块的根连起来,而是对于两个联通块,新建一个点,连向这两个联通块的根结点,而这个新建点的点权就是这条边的边权。

    注意到这样做生成的树有一些性质:

    1.这是一棵二叉树。

    2.原树点都是叶子结点。

    3.子结点比父结点点权小(大根堆)。

    4.原树与新树两点间路径最大值与新树相等,且等于新树两点$lca$点权。

    然后我们发现,对于任意一个$v$,我们向上找到深度最小的满足点权$<=x$的点,然后查询整个子树的第$k$大,就是答案了。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <cstdio>
      7 #include <vector>
      8 #include <cmath>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #define inf (1<<30)
     14 #define N (200010)
     15 #define il inline
     16 #define RG register
     17 #define ll long long
     18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     19 
     20 using namespace std;
     21 
     22 struct edge{ int nt,to; }G[N<<1];
     23 struct E{ int u,v,w; }g[N<<2];
     24 
     25 int head[N],top[N],fa[N],son[N],dep[N],pos[N],dfn[N],ed[N],sz[N],hsh[N],h[N],d[N];
     26 int sum[20*N],ls[20*N],rs[20*N],rt[N],Sz,n,m,Q,RT,num,cnt,tot,ans;
     27 
     28 il int gi(){
     29     RG int x=0,q=1; RG char ch=getchar();
     30     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     31     if (ch=='-') q=-1,ch=getchar();
     32     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
     33     return q*x;
     34 }
     35 
     36 il void insert(RG int from,RG int to){
     37     G[++num]=(edge){head[from],to},head[from]=num; return;
     38 }
     39 
     40 il int cmp(const E &a,const E &b){ return a.w<b.w; }
     41 
     42 il int find(RG int x){ return (!fa[x] || fa[x]==x) ? x : fa[x]=find(fa[x]); }
     43 
     44 il void dfs1(RG int x,RG int p){
     45     fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG int v;
     46     for (RG int i=head[x];i;i=G[i].nt){
     47     v=G[i].to; if (v==p) continue;
     48     dfs1(v,x),sz[x]+=sz[v];
     49     if (sz[son[x]]<=sz[v]) son[x]=v;
     50     }
     51     return;
     52 }
     53 
     54 il void dfs2(RG int x,RG int p,RG int anc){
     55     top[x]=anc,dfn[x]=++cnt,pos[cnt]=x;
     56     if (son[x]) dfs2(son[x],x,anc); RG int v;
     57     for (RG int i=head[x];i;i=G[i].nt){
     58     v=G[i].to; if (v==p || v==son[x]) continue;
     59     dfs2(v,x,v);
     60     }
     61     ed[x]=cnt; return;
     62 }
     63 
     64 il int lca(RG int x,RG int k){
     65     RG int la=x; while (x && d[top[x]]<=k) la=top[x],x=fa[top[x]];
     66     if (d[x]>k || d[top[x]]<=k) return la;
     67     RG int l=dfn[top[x]],r=dfn[x],mid,res;
     68     while (l<=r){
     69     mid=(l+r)>>1;
     70     if (d[pos[mid]]<=k) res=pos[mid],r=mid-1; else l=mid+1;
     71     }
     72     return res;
     73 }
     74 
     75 il void add(RG int x,RG int &y,RG int l,RG int r,RG int v){
     76     sum[y=++Sz]=sum[x]+1,ls[y]=ls[x],rs[y]=rs[x];
     77     if (l==r) return; RG int mid=(l+r)>>1;
     78     v<=mid?add(ls[x],ls[y],l,mid,v):add(rs[x],rs[y],mid+1,r,v); return;
     79 }
     80 
     81 il int query(RG int x,RG int y,RG int l,RG int r,RG int k){
     82     if (l==r) return hsh[l]; RG int mid=(l+r)>>1,tmp=sum[rs[y]]-sum[rs[x]];
     83     return k<=tmp?query(rs[x],rs[y],mid+1,r,k):query(ls[x],ls[y],l,mid,k-tmp);
     84 }
     85 
     86 il void work(){
     87     n=gi(),m=gi(),Q=gi();
     88     for (RG int i=1;i<=n;++i) fa[i]=i,h[i]=gi(),hsh[++tot]=h[i];
     89     sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1;
     90     for (RG int i=1;i<=n;++i) h[i]=lower_bound(hsh+1,hsh+tot+1,h[i])-hsh;
     91     for (RG int i=1;i<=m;++i) g[i].u=gi(),g[i].v=gi(),g[i].w=gi();
     92     sort(g+1,g+m+1,cmp),cnt=n;
     93     for (RG int i=1,k=0,x,y;i<=m;++i){
     94     x=find(g[i].u),y=find(g[i].v); if (x==y) continue;
     95     fa[x]=fa[y]=++cnt,insert(cnt,x),insert(cnt,y);
     96     d[cnt]=g[i].w,RT=cnt,++k; if (k==n-1) break;
     97     }
     98     cnt=0,dfs1(RT,0),dfs2(RT,0,RT);
     99     for (RG int i=1;i<=cnt;++i)
    100     if (pos[i]>n) rt[i]=rt[i-1];
    101     else add(rt[i-1],rt[i],1,tot,h[pos[i]]);
    102     for (RG int i=1,v,x,k,Lca;i<=Q;++i){
    103     v=gi()^ans,x=gi()^ans,k=gi()^ans,Lca=lca(v,x);
    104     if (sum[rt[ed[Lca]]]-sum[rt[dfn[Lca]-1]]<k) ans=0,puts("-1");
    105     else ans=query(rt[dfn[Lca]-1],rt[ed[Lca]],1,tot,k),printf("%d
    ",ans);
    106     }
    107     return;
    108 }
    109 
    110 int main(){
    111     File("peaks");
    112     work();
    113     return 0;
    114 }
  • 相关阅读:
    俞洪敏励志演讲
    svn 提交排除目录
    (二)2005年我的第一次软件行业创业,烧掉30万、2年时间打水漂的惨痛教训
    COM+ System Application 服务无法启动方法
    版本库迁移(合并)的实现
    没有为此解决方案配置选中要生成的项目
    Oracle 10g 下载地址
    JQuery插件开发[转]
    Web开发中的Form Submit Successful
    网页栅格系统研究(4):技术实现
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7197884.html
Copyright © 2011-2022 走看看