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\n",w[qwq]-Ans);
        }
    }
}

 

posted @ 2019-10-29 17:02  si_nian  阅读(156)  评论(0编辑  收藏  举报