zoukankan      html  css  js  c++  java
  • 【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

    这题真刺激......

    I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树。(看一下内容之前请先进门坐一坐)

    II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组。

    |||.我们跑出来dfs序就能在他的上面进行主席树了。

    IV.别忘了离散。

    V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是......

    #include <cstdio>
    #include <algorithm>
    #define N 150000
    #define M 550000
    using namespace std;
    inline int read()
    {
      register int sum=0;
      register char ch=getchar();
      while(ch<'0'||ch>'9')ch=getchar();
      while(ch>='0'&&ch<='9'){
        sum=(sum<<1)+(sum<<3)+ch-'0';
        ch=getchar();
      }
      return sum;
    }
    int n,m,Q;
    struct E{
      int x,y,z;
    }e[M+10];
    int comp(const E a,const E b){
      return a.z<b.z;
    }
    struct Via{
      int to,next;
    }c[M];
    int head[M>>1],t;
    int h[N+10],dfs[M>>1],l[M>>1],r[M>>1],Time;
    int len,Hash[N+10];
    struct Seg_Tree{
      Seg_Tree *ch[2];
      int l,r,size;
    }*root[M>>1],*null;
    int d[M>>1][20],f[M>>1][20],P[N+10],fa[M>>1];
    int Comp(const int x,const int y){
      return h[x]>h[y];
    }
    //*********************Define***********************
    inline Seg_Tree *New(int l,int r){
      register Seg_Tree *p=new Seg_Tree;
      p->l=l,p->r=r,p->size=0,p->ch[0]=p->ch[1]=null;
      return p;
    }
    void ins(Seg_Tree *&p,Seg_Tree *last,int z,int y,int key)
    {
      p=New(z,y),p->size=last->size,p->size++;
      if(p->l==p->r) return; 
      p->ch[0]=last->ch[0],p->ch[1]=last->ch[1];
      if(key<=((z+y)>>1))ins(p->ch[0],last->ch[0],z,((z+y)>>1),key);
      else ins(p->ch[1],last->ch[1],((z+y)>>1)+1,y,key);
    }
    int query(Seg_Tree *a,Seg_Tree *b,int k,int z,int y)
    {
      if(z==y)return z;
      if(a->ch[0]->size-b->ch[0]->size>=k)return query(a->ch[0],b->ch[0],k,z,(z+y)>>1);
      else return query(a->ch[1],b->ch[1],k-(a->ch[0]->size-b->ch[0]->size),((z+y)>>1)+1,y);
    }
    //*********************Seg_Tree*********************
    inline void add(int x,int y){
      c[++t].to=y;
      c[t].next=head[x];
      head[x]=t;
    }
    inline int find(int x){
      return x==fa[x]?x:(fa[x]=find(fa[x]));
    }
    inline int Max(int x,int y){
      return x>y?x:y;
    }
    void Dfs(int x){
      l[x]=++Time,dfs[Time]=x;
      for(register int i=1;i<20;i++)f[x][i]=f[f[x][i-1]][i-1];
      for(register int i=1;i<20;i++)d[x][i]=Max(d[x][i-1],d[f[x][i-1]][i-1]);
      for(register int i=head[x];i;i=c[i].next)Dfs(c[i].to);
      r[x]=Time;
    }
    inline void Kruskal(){
      sort(e+1,e+m+1,comp);
      for(register int i=1;i<=n+n;i++)fa[i]=i;
      for(register int i=1,had=0;had<n-1&&i<=m;i++)
      if(find(e[i].x)!=find(e[i].y)){
        register int X=find(e[i].x),Y=find(e[i].y);
        had++,add(had+n,X),add(had+n,Y),d[X][0]=d[Y][0]=e[i].z;
        f[X][0]=f[Y][0]=fa[X]=fa[Y]=had+n;
      }
      for(register int i=1;i<=n;i++)
        if(!l[find(i)])Dfs(find(i));
    }
    inline int get_root(int x,int lim)
    {
      for(register int i=19;i>=0;i--)
        if(f[x][i]&&d[x][i]<=lim)
          x=f[x][i];
      return x;
    }
    //********************Kruskal************************
    inline void HASH(){
      sort(P+1,P+n+1,Comp);
      for(register int i=1;i<=n;i++)
        if(i==1||h[P[i]]!=h[P[i-1]])
          Hash[++len]=h[P[i]],h[P[i]]=len;
        else h[P[i]]=len;
    }
    //********************Hash***************************
    inline void Init(){
      n=read(),m=read(),Q=read(),null=New(0,0),null->ch[0]=null->ch[1]=null,root[0]=null;
      for(register int i=1;i<=n;i++)h[i]=read(),P[i]=i;HASH();
      for(register int i=1;i<=m;i++)e[i].x=read(),e[i].y=read(),e[i].z=read();Kruskal();
      for(register int i=1;i<=Time;i++)
        if(dfs[i]<=n)  root[i]=null,ins(root[i],root[i-1],1,len,h[dfs[i]]);
        else root[i]=root[i-1];
    }
    inline void Work(){
        register int v,x,k,ans=0;
        while(Q--){
        v=read(),x=read(),k=read();
        register int Root=get_root(v,x);
        if(root[r[Root]]->size-root[l[Root]-1]->size<k){
          puts("-1"),ans=0;continue;
        }
        printf("%d
    ",(ans=Hash[query(root[r[Root]],root[l[Root]-1],k,1,len)]));
      }
    }
    int main(){
      Init();
      Work();
      return 0;
    }
  • 相关阅读:
    VysorPro助手
    Play 2D games on Pixel running Android Nougat (N7.1.2) with Daydream View VR headset
    Play 2D games on Nexus 6P running Android N7.1.1 with Daydream View VR headset
    Native SBS for Android
    ADB和Fastboot最新版的谷歌官方下载链接
    How do I install Daydream on my phone?
    Daydream Controller手柄数据的解析
    蓝牙BLE传输性能及延迟分析
    VR(虚拟现实)开发资源汇总
    Android(Java)控制GPIO的方法及耗时分析
  • 原文地址:https://www.cnblogs.com/TSHugh/p/7270804.html
Copyright © 2011-2022 走看看