• bzoj4336: BJOI2015 骑士的旅行


    Description

    在一片古老的土地上,有一个繁荣的文明。
    这片大地几乎被森林覆盖,有N座城坐落其中。巧合的是,这N座城由恰好N-1条双
    向道路连接起来,使得任意两座城都是连通的。也就是说,这些城形成了树的结构,任意两
    座城之间有且仅有一条简单路径。
    在这个文明中,骑士是尤其受到尊崇的职业。任何一名骑士,都是其家族乃至家乡的荣
    耀。Henry从小就渴望成为一名能守护家乡、驱逐敌人的骑士。勤奋训练许多年后,Henry
    终于满18岁了。他决定离开家乡,向那些成名已久的骑士们发起挑战!
    根据Henry的调查,大陆上一共有M名受封骑士,不妨编号为1到M。
    第i个骑士居住在城Pi,武力值为Fi。
    Henry计划进行若干次旅行,每次从某座城出发沿着唯一的简单路径前往另一座城,
    同时会挑战路线上武力值最高的K个骑士(Henry的体力有限,为了提高水平,当然要挑
    战最强的骑士)。如果路线上的骑士不足K人,Henry会挑战遇到的所有人。
    每次旅行前,可能会有某些骑士的武力值或定居地发生变化,Henry自然会打听消息,
    并对计划做出调整。
    为了在每次旅行时做好充分准备,Henry希望你能帮忙在每次旅行前计算出这条路线
    上他将挑战哪些对手。

    Input

    第一行,一个整数N,表示有N座城,编号为1~N。
    接下来N-1行,每行两个整数Ui和Vi,表示城Ui和城Vi之间有一条道路相连。
    第N+1行,一个整数M,表示有M个骑士。
    接下来M行,每行两个整数Fi和Pi。按顺序依次表示编号为1~M的每名骑士的武
    力值和居住地。
    第N+M+2行,两个整数Q,K,分别表示操作次数和每次旅行挑战的骑士数目上限。
    接下来Q行,每行三个整数Ti,Xi,Yi。Ti取值范围为{1,2,3},表示操作类型。
    一共有以下三种类型的操作:
    Ti=1时表示一次旅行,Henry将从城Xi出发前往城市Yi;
    Ti=2时表示编号为Xi的骑士的居住地搬到城Yi;
    Ti=3时表示编号为Xi的骑士的武力值修正为Yi。

    Output

    输出若干行,依次为每个旅行的答案。
    对每个Ti=1的询问,输出一行,按从大到小的顺序输出Henry在这次旅行中挑战的
    所有骑士的武力值。如果路线上没有骑士,输出一行,为一个整数-1。
    对每个点用multiset维护点权,树链剖分+线段树维护区间上前k大的数(降序),对于查询可以把对应的区间提取出来用堆维护一下多路归并求出前k大
    单次查询时间复杂度约为O((log^2(n)+k)log(log^2(n))),修改为O(klogn)
    #include<bits/stdc++.h>
    const int N=40007;
    char buf[N*100],*ptr=buf-1;
    int _(){
        int x=0,c=*++ptr;
        while(c<48)c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x;
    }
    int n,m,q,k;
    int es[N*2],enx[N*2],e0[N],ep=2;
    std::multiset<int,std::greater<int> >vs[N];
    int as[N],bs[N];
    int fa[N],sz[N],son[N],dep[N],top[N],id[N],idr[N],idp=0;
    int _l,_r,*Q[N],qp;
    bool cmp(int*a,int*b){
        return *a<*b;
    }
    void push(int*a){
        Q[qp++]=a;
        std::push_heap(Q,Q+qp,cmp);
    }
    struct node{
        node*lc,*rc,*f;
        int L,R;
        int v[21];
        void init(int x){
            int p=0;
            for(std::multiset<int>::iterator it=vs[x].begin();p<k&&it!=vs[x].end();v[p++]=*(it++));
            for(;p<k;v[p++]=-1);
        }
        void up(){
            int p=0,p1=0,p2=0,*v1=lc->v,*v2=rc->v;
            while(p<k&&p1<k&&p2<k)v[p++]=v1[p1]>v2[p2]?v1[p1++]:v2[p2++];
            while(p<k&&p1<k)v[p++]=v1[p1++];
            while(p<k&&p2<k)v[p++]=v2[p2++];
        }
        void upds(){
            for(node*w=f;w;w->up(),w=w->f);
        }
        void get(){
            if(_l<=L&&R<=_r){
                if(~v[0])push(v);
                return;
            }
            int M=L+R>>1;
            if(_l<=M)lc->get();
            if(_r>M)rc->get();
        }
    }ns[N*2],*np=ns,*rt[N],*pos[N];
    node*build(int L,int R){
        node*w=np++;
        w->L=L;w->R=R;
        memset(w->v,-1,sizeof(w->v));
        if(L!=R){
            int M=L+R>>1;
            (w->lc=build(L,M))->f=
            (w->rc=build(M+1,R))->f=w;
            w->up();
        }else{
            pos[idr[L]]=w;
            w->init(idr[L]);
        }
        return w;
    }
    void f1(int w,int pa){
        dep[w]=dep[fa[w]=pa]+1;
        sz[w]=1;
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=pa){
                f1(u,w);
                sz[w]+=sz[u];
                if(sz[u]>sz[son[w]])son[w]=u;
            }
        }
    }
    void f2(int w,int tp){
        top[w]=tp;
        idr[id[w]=++idp]=w;
        if(son[w])f2(son[w],tp);
        else rt[tp]=build(id[tp],id[w]);
        for(int i=e0[w];i;i=enx[i]){
            int u=es[i];
            if(u!=fa[w]&&u!=son[w])f2(u,u);
        }
    }
    int main(){
        buf[fread(buf,1,sizeof(buf),stdin)]=0;
        n=_();
        for(int i=1,a,b;i<n;++i){
            a=_();b=_();
            es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
            es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
        }
        m=_();
        for(int i=1;i<=m;++i){
            as[i]=_();bs[i]=_();
            vs[bs[i]].insert(as[i]);
        }
        q=_();k=_();
        f1(1,0);f2(1,1);
        for(int i=0,o,x,y;i<q;++i){
            o=_();x=_();y=_();
            if(o==1){
                qp=0;
                int a=top[x],b=top[y];
                while(a!=b){
                    if(dep[a]<dep[b])std::swap(x,y),std::swap(a,b);
                    _l=id[a],_r=id[x],rt[a]->get();
                    x=fa[a];a=top[x];
                }
                if(dep[x]>dep[y])std::swap(x,y);
                _l=id[x],_r=id[y],rt[top[x]]->get();
                if(!qp)printf("-1");
                for(int j=0;j<k&&qp;++j){
                    int*p=Q[0];
                    std::pop_heap(Q,Q+qp--,cmp);
                    printf("%d ",*p);
                    if(~*++p)push(p);
                }
                putchar(10);
            }else if(o==2){
                vs[bs[x]].erase(vs[bs[x]].find(as[x]));
                pos[bs[x]]->init(bs[x]);
                pos[bs[x]]->upds();
                vs[bs[x]=y].insert(as[x]);
                pos[bs[x]]->init(bs[x]);
                pos[bs[x]]->upds();
            }else{
                vs[bs[x]].erase(vs[bs[x]].find(as[x]));
                vs[bs[x]].insert(as[x]=y);
                pos[bs[x]]->init(bs[x]);
                pos[bs[x]]->upds();
            }
        }
        return 0;
    }
  • 相关阅读:
    hdu 1312 Red and Black
    hdu 1573 X问题
    广工校赛决赛之简单的数论题
    最大的LeftMax与rightMax之差绝对值
    POJ 2385 Apple Catching
    hdu 1171 Big Event in HDU
    ACM比赛经验
    BestCoder Valentine's Day Round
    使用ffmpeg进行视频封面截取
    使用ODP.NET连接Oracle数据库
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6417710.html
Copyright © 2020-2023  润新知