• [堆][启发式合并]luogu P3261 [JLOI2015]城池攻占


    题面

    https://www.luogu.com.cn/problem/P3261

    分析

    考虑对于每个点开堆维护子树中到达这里的所有人的攻击力

    对于攻击力改变可以用标记数组给堆打上标记

    自下向上合并时,选择较小的堆合并给较大的堆,注意修改每个节点对应的堆编号

    当一个值要合并入一个有标记的堆时,直接给这个值除标记值或者减标记值消除标记的影响

    记录一下哪些值在哪里被从堆中删除即可

    代码

    //Tempestissimo 
    #include <iostream>
    #include <cstdio>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int N=3e5+10;
    struct Graph {
        int v,nx;
    }g[N];
    int list[N],cnt,a[N],c[N],dep[N],dth[N],bel[N],ans[N];
    ll h[N],v[N],pls[N],multi[N];
    int n,m;
    
    ll GCD(ll a,ll b) {return !b?a:GCD(b,a%b);}
    
    struct Num {
        int id;
        ll num,deno;
        
        friend bool operator < (Num a,Num b) {return (long double)a.num/a.deno>(long double)b.num/b.deno;}
        
        friend Num operator * (Num a,ll b) {ll gcd=GCD(a.deno,b);a.deno/=gcd;b/=gcd;a.num*=b;return a;}
        
        friend Num operator / (Num a,ll b) {ll gcd=GCD(a.num,b);a.num/=gcd;b/=gcd;a.deno*=b;return a;}
        
        friend Num operator + (Num a,ll b) {a.num+=b*a.deno;ll gcd=GCD(a.num,a.deno);a.num/=gcd;a.deno/=gcd;return a;}
    };
    priority_queue<Num> q[N];
    
    void Add(int u,int v) {g[++cnt]=(Graph){v,list[u]};list[u]=cnt;}
    
    void Merge(int &x,int &y) {
        if (q[x].size()<q[y].size()) swap(x,y);
        while (!q[y].empty()) {
            Num temp=q[y].top();q[y].pop();
            temp=(((temp*multi[y])+pls[y])+(-pls[x]))/multi[x];
            q[x].push(temp);
        }
    }
    
    void DFS(int u) {
        for (int i=list[u];i;i=g[i].nx) dep[g[i].v]=dep[u]+1,DFS(g[i].v),Merge(bel[u],bel[g[i].v]);
        while (!q[bel[u]].empty()) {
            Num temp=q[bel[u]].top();
            temp=(temp*multi[bel[u]])+pls[bel[u]];
            if ((long double)temp.num/temp.deno>=(long double)h[u]) break;
            ans[dth[temp.id]=u]++;q[bel[u]].pop();
        }
        if (a[u]) multi[bel[u]]*=v[u],pls[bel[u]]*=v[u];
        else pls[bel[u]]+=v[u];
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%lld",&h[i]),bel[i]=i,multi[i]=1;
        for (int i=2,f;i<=n;i++) scanf("%d%d%lld",&f,&a[i],&v[i]),Add(f,i);
        for (int i=1;i<=m;i++) {ll s;scanf("%lld%d",&s,&c[i]);q[c[i]].push((Num){i,s,1});}
        dep[1]=1;DFS(1);
        for (int i=1;i<=n;i++) printf("%d
    ",ans[i]);
        for (int i=1;i<=m;i++) printf("%d
    ",dep[c[i]]-dep[dth[i]]);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    对scott中emp表进行各种操作
    可兼容的事件绑定方法
    深度复制
    原型链的继承
    如何在github上发布自己的项目
    用单例连接oracle数据库
    Struts2之输入验证
    JSP之监听器Listener(二)
    JSP之监听器Listener(一)————————ServletContextListener
    JSP之过滤器Filter
  • 原文地址:https://www.cnblogs.com/mastervan/p/14543324.html
Copyright © 2020-2023  润新知