zoukankan      html  css  js  c++  java
  • [圆方树][树链剖分][set]JZOJ 5909 跑商

    Description

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

    Input

    第一行 n,m;
    接下来 1 行 n 个数,代表每个城市货物的价格;
    接下来 m 行 u,v 代表一条边
    接下来 1 行 Q
    接下来 Q 行
    C x w 代表城市 x 的货物价格变为 w
    Q u v 代表一次从 u 到 v 的跑商

    Output

    如题目描述
     

    Sample Input

    3 3 
    1 2 3
    1 2
    2 3
    1 3
    3
    Q 2 3
    C 1 5
    Q 1 3
     

    Sample Output

    1
    3
    
    样例解释:
    1,2,3 都联通,起点购买价格为 2,在 1 点卖出赔得最多2-1=1
    更新后每个点价值为 5,2,3
    起点价格为 5,在 2 点卖出赔得最多,5-2=3
     

    Data Constraint

    40%的数据为一棵树
    另外 20%的数据没有修改操作
    所以数据满足 n,m,q<=100000;保证图联通,数据合法
     

    Hint

    Tips:数据很水可以尝试瞎搞算法,1,2 两道题算法我暑假讲过类似的,各位随便 AC,第三题应该有不少大佬见过原题 orz。

    分析

    原题怪!

    这题我们转换成圆方树,然后对于方点,我们储存的值为所连叶子节点的最小值(虽然父亲也是环的一部分但是算进去很麻烦)用set维护

    然后树链剖分即可

    对于LCA为方点的特殊情况,我们要特判一下它的父亲

    #include <iostream>
    #include <cstdio>
    #include <set>
    #include <stack>
    using namespace std;
    const int N=1e6+10;
    struct Node {
        int sz,son,top,fa,seg,dep,w;
    }t[N];
    int rev[N],scnt;
    struct Edge {
        int u,v,nx;
    }g[4*N],e[2*N];
    int cnt,elist[N],list[2*N];
    int s[4*N];
    int low[N],dfn[N],tme;
    stack<int> stk;
    multiset<int> sqr[N];
    int sqcnt;
    int n,m,q;
    
    void Adde(int u,int v) {
        e[++cnt].u=u;e[cnt].v=v;e[cnt].nx=elist[u];elist[u]=cnt;
    }
    
    void Add(int u,int v) {
        g[++cnt].u=u;g[cnt].v=v;g[cnt].nx=list[u];list[u]=cnt;
    }
    
    void Tarjan(int u,int fa) {
        low[u]=dfn[u]=++tme;stk.push(u);
        for (int i=elist[u];i;i=e[i].nx)
            if (e[i].v!=fa)
                if (!dfn[e[i].v]) {
                    Tarjan(e[i].v,u);
                    if (low[e[i].v]>=dfn[u]) {
                        Add(++sqcnt,u);Add(u,sqcnt);
                        while (!stk.empty()&&stk.top()!=e[i].v) Add(sqcnt,stk.top()),Add(stk.top(),sqcnt),stk.pop();
                        Add(sqcnt,e[i].v),Add(e[i].v,sqcnt),stk.pop();
                    }
                    else low[u]=min(low[u],low[e[i].v]);
                }
                else low[u]=min(low[u],dfn[e[i].v]);
    }
    
    void Dfs1(int u,int fa) {
        t[u].fa=fa;t[u].sz=1;t[u].dep=t[fa].dep+1;
        if (fa>n) sqr[fa-n].insert(t[u].w);
        for (int i=list[u];i;i=g[i].nx)
            if (g[i].v!=fa) {
                Dfs1(g[i].v,u);
                t[u].sz+=t[g[i].v].sz;
                if (t[g[i].v].sz>t[t[u].son].sz) t[u].son=g[i].v;
            }
    }
    
    void Dfs2(int u,int fa) {
        int son=t[u].son;
        if (u>n) t[u].w=*sqr[u-n].begin();
        if (son) {
            t[son].seg=++scnt;
            rev[scnt]=son;
            t[son].top=t[u].top;
            Dfs2(son,u);
        }
        for (int i=list[u];i;i=g[i].nx)
            if (!t[g[i].v].top) {
                t[g[i].v].seg=++scnt;
                rev[scnt]=g[i].v;
                t[g[i].v].top=g[i].v;
                Dfs2(g[i].v,u);
            }
    }
    
    void Build(int l,int r,int x) {
        if (l==r) {
            s[x]=t[rev[l]].w;
            return;
        }
        int mid=l+r>>1;
        Build(l,mid,x<<1);Build(mid+1,r,(x<<1)+1);
        s[x]=min(s[x<<1],s[(x<<1)+1]);
    }
    
    void Change(int l,int r,int w,int k,int x) {
        if (l>k||k>r) return;
        if (l==r&&r==k) {
            s[x]=w;
            return;
        }
        int mid=l+r>>1;    
        if (mid>=k) Change(l,mid,w,k,x<<1);
        if (mid<k) Change(mid+1,r,w,k,(x<<1)+1);
        s[x]=min(s[x<<1],s[(x<<1)+1]);
    }
    
    int Query_Seg(int l,int r,int ll,int rr,int x) {
        if (l>rr||ll>r) return 2147483647;
        if (ll<=l&&r<=rr) return s[x];
        int mid=l+r>>1,ans=2147483647;
        if (ll<=mid) ans=Query_Seg(l,mid,ll,rr,x<<1);
        if (mid<rr) ans=min(ans,Query_Seg(mid+1,r,ll,rr,(x<<1)+1));
        return ans;
    }
    
    int Query_Tree(int x,int y) {
        int fx=t[x].top,fy=t[y].top;
        int ans=2147483647;
        while (fx!=fy) {
            if (t[fx].dep<t[fy].dep) swap(x,y),swap(fx,fy);
            ans=min(ans,Query_Seg(1,scnt,t[fx].seg,t[x].seg,1));
            x=t[fx].fa;fx=t[x].top;
        }
        if (t[x].dep>t[y].dep) swap(x,y);
        return min(min(ans,x>n?t[t[x].fa].w:2147483647),Query_Seg(1,scnt,t[x].seg,t[y].seg,1));
    }
    
    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",&t[i].w);
        for (int i=1;i<=m;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            Adde(u,v);Adde(v,u);
        }
        sqcnt=n;cnt=0;Tarjan(1,0);
        Dfs1(1,0);
        scnt=rev[1]=t[1].top=t[1].seg=1;
        Dfs2(1,0);
        Build(1,scnt,1);
        scanf("%d",&q);
        for (int i=1;i<=q;i++) {
            char c;
            do {
                scanf("%c",&c);
            }
            while (c!='Q'&&c!='C');
            int u,v;
            scanf("%d%d",&u,&v);
            if (c=='Q') printf("%d
    ",t[u].w-Query_Tree(u,v));
            else {
                Change(1,scnt,v,t[u].seg,1);
                if (t[u].fa>n) {
                    sqr[t[u].fa-n].erase(sqr[t[u].fa-n].find(t[u].w));
                    sqr[t[u].fa-n].insert(v);
                    int fake=*sqr[t[u].fa-n].begin();
                    if (t[t[u].fa].w!=fake) t[t[u].fa].w=fake,Change(1,scnt,fake,t[t[u].fa].seg,1);
                }
                t[u].w=v;
            }
        }
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    Visual Studio自带的的Developer Command Prompt对话框
    利用VS(Visual Studio)自带的工具查看DLL文件的信息
    谷歌面试官反馈级别
    Inno Setup中多语言时,使用占位符填充
    SQL*Plus命令
    Oracle 所有字典
    彻底完全卸载 SQL Server 2005 的图文教程
    win7(windows 7)系统下安装SQL2005(SQL Server 2005)图文教程
    创建表空间、新增用户、给用户赋予DBA权限 、删除用户下的上有数据表
    ORA-01012: not logged on
  • 原文地址:https://www.cnblogs.com/mastervan/p/9813713.html
Copyright © 2011-2022 走看看