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

    很明显只有最小生成树里面的点有用

    我会一个离线的做法,把询问边长排序,逐步合并树,启发式合并splay

    在线怎么做呢?

    考虑合并出最小生成树的过程,两点合并是并不是一边连向一边而是建出新点,并将新点连向两边边权为这两点的边权。重构出新树后,所有原点都是叶子节点,并且边权深到浅单增,可以用倍增找到断开的位置,问题变成求子树中第k大的值,上一个主席树就好了

    码力堪忧

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int _=1e2;
    const int maxn=1e5+_;
    const int maxp=2*maxn;
    const int maxm=5e5+_;
    const int maxQ=5e5+_;
    int n,m,Q,w[maxn]; int lslen,ls[maxn];
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    inline void write(int d)
    {
        if(d>=10)write(d/10);
        putchar(d%10+'0');
    }
    
    namespace CHAIR
    {
        struct trnode
        {
            int lc,rc,c;
        }tr[12*maxp];int trlen,rt[maxp];
        int maketree(int now,int l,int r,int p)
        {
            if(now==0)now=++trlen;
            tr[now].c++;
            if(l!=r)
            {
                int mid=(l+r)/2;
                if(p<=mid)tr[now].lc=maketree(tr[now].lc,l,mid,p);
                else tr[now].rc=maketree(tr[now].rc,mid+1,r,p);
            }
            return now;
        }
        int merge(int x,int y)
        {
            if(x==0||y==0)return x+y;
            tr[x].c+=tr[y].c;
            tr[x].lc=merge(tr[x].lc,tr[y].lc);
            tr[x].rc=merge(tr[x].rc,tr[y].rc);
            return x;
        }
        int findkth(int x,int y,int l,int r,int k)
        {
            if(tr[y].c-tr[x].c<k)return -1;
            if(l==r)return l;
            int mid=(l+r)/2;
            int c=tr[tr[y].rc].c-tr[tr[x].rc].c;
            if(c>=k)return findkth(tr[x].rc,tr[y].rc,mid+1,r,k);
            else return findkth(tr[x].lc,tr[y].lc,l,mid,k-c);
        }
    }
    
    struct node
    {
        int x,y,d,next;
    }a[maxp];int len,last[maxp];
    void ins(int x,int y,int d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    //    printf("%d %d %d
    ",x,y,d);
    }
    int z,L[maxp],R[maxp],de[maxp];
    int dep[maxp],f[30][maxp];
    void dfs(int x)
    {
        for(int i=1;(1<<i)<=dep[x];i++)f[i][x]=f[i-1][f[i-1][x]];
        L[x]=++z;
        if(last[x]==0)
        {
            CHAIR::rt[z]=CHAIR::maketree(CHAIR::rt[z],1,lslen,w[x]);
            CHAIR::rt[z]=CHAIR::merge(CHAIR::rt[z],CHAIR::rt[z-1]);
        }
        else CHAIR::rt[z]=CHAIR::rt[z-1];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y; de[y]=a[k].d;
            f[0][y]=x;
            dep[y]=dep[x]+1;
            dfs(y);
        }
        R[x]=z;
    }
    
    int fa[maxp];
    int findfa(int x)
    {
        if(fa[x]==x)return x;
        fa[x]=findfa(fa[x]);return fa[x];
    }
    struct edge{int x,y,d;}e[maxm];
    bool cmp(edge e1,edge e2){return e1.d<e2.d;}
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        n=read(),m=read(),Q=read();
        for(int i=1;i<=n;i++)
            w[i]=read(),ls[++lslen]=w[i];
            
        sort(ls+1,ls+lslen+1);
        lslen=unique(ls+1,ls+lslen+1)-ls-1;
        for(int i=1;i<=n;i++)
            w[i]=lower_bound(ls+1,ls+lslen+1,w[i])-ls;
            
        for(int i=1;i<=m;i++)
            e[i].x=read(),e[i].y=read(),e[i].d=read();
        sort(e+1,e+m+1,cmp);
        
        int fx,fy;
        for(int i=1;i<=2*n;i++)fa[i]=i;
        for(int i=1;i<=m;i++)
        {
            fx=findfa(e[i].x),fy=findfa(e[i].y);
            if(fx!=fy)
            {
                n++; fa[fx]=n,fa[fy]=n;
                ins(n,fx,e[i].d);
                ins(n,fy,e[i].d);
            }
        }
        dfs(n);
        
        int x,k,d,lastans=0;
        while(Q--)
        {
            x=read(),d=read(),k=read();
            x^=lastans,k^=lastans,d^=lastans;
            if(de[x]>d)
            {
                if(k==1)lastans=w[x],printf("%d
    ",w[x]);
                else puts("-1"),lastans=0;
                continue;
            }
            for(int i=25;i>=0;i--)
                if((1<<i)<dep[x]&&de[f[i][x]]<=d)x=f[i][x];
            x=f[0][x];
            lastans=CHAIR::findkth(CHAIR::rt[L[x]-1],CHAIR::rt[R[x]],1,lslen,k);
            if(lastans!=-1)
            {
                lastans=ls[lastans];
                write(lastans),putchar('
    ');
            }
            else puts("-1"),lastans=0;
        }
        
        return 0;
    }
  • 相关阅读:
    iBatis——自动生成DAO层接口提供操作函数(详解)
    【Spring Boot项目】Win7+JDK8+Tomcat8环境下的War包部署
    MySQL使用小记
    DB迁移:从SQL Server 2005到MySQL
    【文章学习】监控网页卡顿、崩溃
    为什么执行x in range(y)如此之快
    python笔试题(三)
    python笔试题(二)
    python笔试题(-)
    rest-framework(2)
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10730777.html
Copyright © 2011-2022 走看看