zoukankan      html  css  js  c++  java
  • GMOJ 5909 跑商

    题目背景:
    尊者神高达很穷,所以他需要跑商来赚钱
    题目描述:
    基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖出并最终到达终点,尊者神高达的时间很宝贵,所以他不会重复经过同一个城市,但是为了挣钱,他可能会去绕路。当然,由于工作室泛滥,所以一个城市的货物价格可能会发生改变。但是尊者神高达智商不足,他可能在一个很蠢的节点把货物卖掉,所以尊者神高达想知道每一次跑商最多能赔多少钱。

    sol:

    这不是圆方树模板题嘛

    发现一个点双内的点可以全部取到

    于是直接把圆方树建出来,然后方点用multiset维护一个圆点的最小值

    但是这样发现如果直接更新的话,要更新一圈圆点,所以考虑方点不维护它父亲的值,而是只维护儿子中的圆点值

    然后接下来的问题就是路径最值问题了

    树上路径最值,显然树链剖分

    然后我们就做完了

    lca是方点的时候记得找一下父亲==

    [然后今早tarjan把v写成u,然后就自闭了.jpg]

    [然后还忘记保存本来的x值了……]

    [自闭选手不配ac]

    #include <bits/stdc++.h>
    using namespace std;
    int cnt1,nex1[500005],las1[500005],Arrive1[500005],cnt2,nex2[500005],las2[500005],Arrive2[500005];
    int N,M,Q,Bcc_cnt;
    int w[500005];
    multiset<int> S[500005];
    int dfn[500005],Low[500005],Timew;
    int stk[500005],tp;
    void jt1(int x,int y){
        cnt1++;
        nex1[cnt1]=las1[x];
        las1[x]=cnt1;
        Arrive1[cnt1]=y;
    }
    void jt2(int x,int y){
        cnt2++;
        nex2[cnt2]=las2[x];
        las2[x]=cnt2;
        Arrive2[cnt2]=y; 
    }
    void Tarjan(int Now){
        //cout<<Now<<endl;
        Low[Now]=dfn[Now]=++Timew;
        stk[++tp]=Now;
        for (int i=las1[Now];i;i=nex1[i]){
            if (!dfn[Arrive1[i]]){
                Tarjan(Arrive1[i]);
                Low[Now]=min(Low[Now],Low[Arrive1[i]]);
                if (Low[Arrive1[i]]==dfn[Now]){
                    ++Bcc_cnt;
                    for (int x=0;x!=Arrive1[i];--tp){
                        x=stk[tp];
                        jt2(Bcc_cnt,x);
                        jt2(x,Bcc_cnt);
                    }
                    jt2(Bcc_cnt,Now);
                    jt2(Now,Bcc_cnt);
                }
            }
            else Low[Now]=min(Low[Now],dfn[Arrive1[i]]);
        }
    }
    int idf[500005],fa[500005],Siz[500005],dep[500005],Son[500005],top[500005],dfc;
    void dfs1(int Now,int Fa){
        fa[Now]=Fa;dep[Now]=dep[Fa]+1;Siz[Now]=1;
        for (int i=las2[Now];i;i=nex2[i])
            if (Arrive2[i]!=Fa){
                dfs1(Arrive2[i],Now);
                Siz[Now]+=Siz[Arrive2[i]];
                if (Siz[Son[Now]]<Siz[Arrive2[i]]) Son[Now]=Arrive2[i];
            }
    }
    void dfs2(int Now,int Fa,int tp){
        dfn[Now]=++dfc,idf[dfc]=Now,top[Now]=tp;
        if (Son[Now]) dfs2(Son[Now],Now,tp);
        for (int i=las2[Now];i;i=nex2[i])
            if (Arrive2[i]!=Fa&&Arrive2[i]!=Son[Now])
                dfs2(Arrive2[i],Now,Arrive2[i]);
    }
    int Tree[1000005];
    void Build(int Now,int l,int r){
        if (l==r) {Tree[Now]=w[idf[l]]; return;}
        int mid=(l+r)>>1;
        Build(Now<<1,l,mid),Build(Now<<1|1,mid+1,r);
        Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);    
    }
    void Modify(int Now,int l,int r,int Pos,int x){
        if (l==r) {Tree[Now]=x;return;}
        int mid=(l+r)>>1;
        if (Pos<=mid) Modify(Now<<1,l,mid,Pos,x);
        else Modify(Now<<1|1,mid+1,r,Pos,x);
        Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
    }
    int query(int Now,int l,int r,int L,int R){
        if (r<L||l>R) return 1e9+7;
        if (L<=l&&r<=R) return Tree[Now];
        int mid=(l+r)>>1;
        return min(query(Now<<1,l,mid,L,R),query(Now<<1|1,mid+1,r,L,R));
    }
    int main(){
        freopen("paoshang.in","r",stdin);
        freopen("paoshang.out","w",stdout);
        scanf("%d%d",&N,&M);    
        for (int i=1;i<=N;i++)
            scanf("%d",&w[i]);
        Bcc_cnt=N;
        for (int i=1;i<=M;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            jt1(u,v);
            jt1(v,u);
        }
        Tarjan(1),dfs1(1,0),dfc=0,dfs2(1,0,1);
        for (int i=1;i<=N;i++)
            if (fa[i]) S[fa[i]].insert(w[i]);
        for (int i=N+1;i<=Bcc_cnt;i++)
            w[i]=*S[i].begin();
        Build(1,1,Bcc_cnt);    
        scanf("%d",&Q);
        while (Q--){
            char opt[3];int x,y;
            scanf("%s%d%d",opt,&x,&y);
            if (*opt=='C'){
                Modify(1,1,Bcc_cnt,dfn[x],y);
                if (fa[x]){
                    int u=fa[x];
                    S[u].erase(S[u].lower_bound(w[x]));
                    S[u].insert(y);
                    if (w[u]!=*S[u].begin()){
                        w[u]=*S[u].begin();
                        Modify(1,1,Bcc_cnt,dfn[u],w[u]);
                    }
                }
                w[x]=y;
            }
            else{
                int Ans=1e9+7,qwq=x;
                while (top[x]!=top[y]){
                    if (dep[top[x]]<dep[top[y]]) swap(x,y);
                Ans=min(Ans,query(1,1,Bcc_cnt,dfn[top[x]],dfn[x]));
                x=fa[top[x]];
              }
              if (dfn[x]>dfn[y]) swap(x,y);
              Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
              if (x>N) 
              Ans=min(Ans,w[fa[x]]);
              printf("%d
    ",w[qwq]-Ans);
            }
        }
    }
  • 相关阅读:
    【Python】使用hashlib进行MD5和sha1摘要计算
    【Python】torrentParser1.04 增加获得磁力链URI功能
    day30_Hibernate复习_02
    day30_Hibernate学习笔记_02
    day29_Hibernate复习_01
    day29_Hibernate学习笔记_01
    【重要】Spring在web.xml中的配置原理说明
    HTTP常见错误编号
    一级缓存和二级缓存的理解
    电商网站前台与后台系统架构
  • 原文地址:https://www.cnblogs.com/si--nian/p/11759926.html
Copyright © 2011-2022 走看看