zoukankan      html  css  js  c++  java
  • 可并堆

    左偏树

    bzoj4003 城池攻占

    题目大意:一棵树,每个点有一个防御值。m个武士,有攻击力和起始的位置,攻下一个点后会向父亲进攻,攻击力大于等于一个点的防御力就可以攻下,否则死亡。武士攻下每个点后攻击力会变化,加上或者乘上一个数(乘的数保证非负)。问每个城市死亡的武士个数和每个武士攻下的点。

    思路:用左偏树维护一个点的武士信息,权值的更改用*a+b的形式更新。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 300005
    #define LL long long
    using namespace std;
    struct use{int l,r,d;LL ad,ch;}hp[N];
    struct uu{int ai;LL vi,hi;}ci[N];
    int rt[N]={0},point[N]={0},next[N],cur[N],zh[N],zt,pa[N],ca[N]={0},dis[N]={0};
    LL vi[N];
    void pushdown(int x){
        int l,r;l=hp[x].l;r=hp[x].r;
        if (l){
            vi[l]=vi[l]*hp[x].ch+hp[x].ad;
            hp[l].ad=hp[l].ad*hp[x].ch+hp[x].ad;
            hp[l].ch=hp[l].ch*hp[x].ch;
        }if (r){
            vi[r]=vi[r]*hp[x].ch+hp[x].ad;
            hp[r].ad=hp[r].ad*hp[x].ch+hp[x].ad;
            hp[r].ch=hp[r].ch*hp[x].ch;
        }hp[x].ad=0LL;hp[x].ch=1LL;
    }
    int merge(int x,int y){
        if (!x) return y;
        if (!y) return x;
        pushdown(x);pushdown(y);
        if (vi[x]>vi[y]) swap(x,y);
        hp[x].r=merge(hp[x].r,y);
        if (hp[hp[x].l].d<hp[hp[x].r].d) swap(hp[x].l,hp[x].r);
        if (!hp[x].r) hp[x].d=0;
        else hp[x].d=hp[hp[x].r].d+1;
        return x;}
    void work(int u){
        while(rt[u]&&vi[rt[u]]<ci[u].hi){
            ++ca[u];pushdown(rt[u]);
            pa[rt[u]]=dis[pa[rt[u]]]-dis[u];
            rt[u]=merge(hp[rt[u]].l,hp[rt[u]].r);
        }if (u!=1){
            if (rt[u]){
                if (ci[u].ai==0){
                    vi[rt[u]]+=ci[u].vi;
                    hp[rt[u]].ad+=ci[u].vi;
                }else{
                    vi[rt[u]]*=ci[u].vi;
                    hp[rt[u]].ad*=ci[u].vi;
                    hp[rt[u]].ch*=ci[u].vi;
                }
            }
        }else
            while(rt[u]){
                pushdown(rt[u]);
                pa[rt[u]]=dis[pa[rt[u]]]-dis[u]+1;
                rt[u]=merge(hp[rt[u]].l,hp[rt[u]].r);
            }
    }
    int main(){
        int n,m,i,fi,u,v;
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;++i) scanf("%I64d",&ci[i].hi);
        for (i=2;i<=n;++i){
            scanf("%d%d%I64d",&fi,&ci[i].ai,&ci[i].vi);
            next[i]=point[fi];cur[fi]=point[fi]=i;
        }for (i=1;i<=m;++i){
            scanf("%I64d%d",&vi[i],&fi);
            pa[i]=fi;
            hp[i]=(use){0,0,0,0LL,1LL};
            rt[fi]=merge(rt[fi],i);
        }zh[zt=1]=1;dis[1]=1;
        while(zt){
            u=zh[zt];
            if ((v=cur[u])>0){
                dis[v]=dis[u]+1;
                zh[++zt]=v;
                cur[u]=next[v];
            }else{
                --zt;
                for (v=point[u];v;v=next[v])
                    rt[u]=merge(rt[u],rt[v]);
                work(u);
            }
        }for (i=1;i<=n;++i) printf("%d
    ",ca[i]);
        for (i=1;i<=m;++i) printf("%d
    ",pa[i]);
    }
    View Code

    bzoj4524 伪光滑数

    题目大意:x的最大质因子ak,分解后有k项(9=3*3,算两项),ak^k<=N,问第e大的数x是多少。

    思路:优先队列保存最大的质因数是x,有y项的最大数(!!)。fi[i][j]表示最大质因数是i,有j项的数的堆,gi[i][j]表示最大质因数至多到i,有j项的数的堆。找次大数的时候可以用可持久化左偏堆维护,因为会不断建点,所以防止mle。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #define N 128
    #define up 61
    #define len 16000000
    #define LL long long
    using namespace std;
    struct use{
        int x,y;LL v;
        bool operator<(const use&x)const{return v<x.v;}
    };
    struct hp{int l,r,d;LL v,del;}zh[len];
    int fi[N][up]={0},gi[N][up]={0},pr[N],flag[N]={0},zt=0;
    LL vi[N][up],n;
    priority_queue<use> que;
    int getn(int o){
        if (!o) return 0;
        zh[++zt]=zh[o];return zt;}
    int add(int o,LL x){
        if (!o) return o;
        int ci=getn(o);
        zh[ci].del*=x;zh[ci].v*=x;
        return ci;}
    void pushdown(int o){
        if (zh[o].del==1LL) return;
        zh[o].l=add(zh[o].l,zh[o].del);
        zh[o].r=add(zh[o].r,zh[o].del);
        zh[o].del=1LL;}
    int merge(int a,int b){
        if (!a) return b;
        if (!b) return a;
        pushdown(a);pushdown(b);
        if (zh[a].v<zh[b].v) swap(a,b);
        int c1=getn(a);
        zh[c1].r=merge(zh[c1].r,b);
        if ((!zh[c1].l?0:zh[zh[c1].l].d)<(!zh[c1].r?0:zh[zh[c1].r].d))
            swap(zh[c1].l,zh[c1].r);
        if (!zh[c1].r) zh[c1].d=1;
        else zh[c1].d=zh[zh[c1].r].d+1;
        return c1;}
    void del(int &o){
        if (!o) return;
        pushdown(o);
        o=merge(zh[o].l,zh[o].r);}
    void pre(int nn){
        int i,j,k,ci;
        for (i=2;i<nn;++i){
            if (!flag[i]) pr[++pr[0]]=i;
            for (j=1;j<=pr[0]&&i*pr[j]<nn;++j){
                flag[i*pr[j]]=true;
                if (i%pr[j]==0) break;
            }
        }memset(vi,0,sizeof(vi));
        for (i=1;i<=pr[0];++i){
            vi[i][0]=1LL;
            for (vi[i][j=1]=(LL)pr[i];vi[i][j]<=n&&vi[i][j]>vi[i][j-1];){
                ++j;vi[i][j]=vi[i][j-1]*(LL)pr[i];
            }vi[i][j]=0LL;
        }gi[0][0]=zt=1;
        zh[1]=(hp){0,0,0,1LL,1LL};
        for (i=1;i<=pr[0];++i){
            gi[i][0]=1;
            for (j=1;vi[i][j];++j){
                for (k=1;k<=j;++k)
                    if (gi[i-1][j-k]){
                        ci=add(gi[i-1][j-k],vi[i][k]);
                        fi[i][j]=merge(fi[i][j],ci);
                    }
                gi[i][j]=merge(fi[i][j],gi[i-1][j]);
                que.push((use){i,j,zh[fi[i][j]].v});
            }
        }
    }
    int main(){
        LL ans;use ci;
        int k,i,j,mx;scanf("%I64d%d",&n,&k);
        pre(N);
        while(k--){
            ci=que.top();que.pop();
            ans=ci.v;
            del(fi[ci.x][ci.y]);
            if (fi[ci.x][ci.y]){
                ci.v=zh[fi[ci.x][ci.y]].v;
                que.push(ci);
            }
        }printf("%I64d
    ",ans);
    }
    View Code

    (一开始想的保存所有质因数是第几个,维护一个递增序列,用treap维护,但复杂度过不去)

  • 相关阅读:
    ES6的Proxy对象
    ES6的Reflect对象
    v-for中的key
    v-for和v-if的问题
    request请求的get/post的模块的封装
    HTTP 协议和接口分类
    cookies和session区别
    面试题目:接口访问中遇到验证码,怎么解决?
    数据驱动_Excel操作
    python完成http请求 get,post
  • 原文地址:https://www.cnblogs.com/Rivendell/p/5342801.html
Copyright © 2011-2022 走看看