• 2017多校第9场 HDU 6161 Big binary tree 思维,类似字典树


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6161

    题意:

    题目是给一棵完全二叉树,从上到下从左到右给每个节点标号,每个点有权值,初始权值为其标号,然后有两种操作:
    1、把u点权值改为x
    2、查询所有经过u点的路径中,路径上的点权和最大。
    节点有n个,修改有m个,n<=1e8 ,m<= 1e5

    解法:现场队友过的,orz,来自队友的思路。

    我们首先对于一个点,如果没有访问我们不把它建出来,相反访问了就把它建出来,这个题的最小的子问题就是计算一个节点的答案怎么算,我们直接往右子树怼?显然并不全是,我们发现从n上来这一条链上的节点的答案并不一定是一直往右走,所以我们特殊处理这条链就可以 了。这就解决了最小的子问题,用log2n的复杂度算出了每个节点的答案,接下来就是更新和查询,更新的话,我们先更新这个节点,然后从这个节点到1这条链上的点都要更新,我们直接更新上去即可,对于查询来说,和更新一样我们只需要关心这个点所在的链上的信息,所以我们直接往上跑并且查询,这里查询就要贪心一下,如果有左儿子就累加上靠右儿子的答案,否则累加左儿子的答案,这里画个图模拟一下即可,这些点的信息可以用unorder_map和unorder_set来方便的维护,复杂度O(logn*logn)。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    unordered_map<int,pair<LL,LL> >mp;//u点,左儿子,右儿子
    unordered_map<int,LL>now;//现在这个u节点的值
    unordered_set<int>st;//题解上说的那条特殊链
    int n,m;
    LL cal(int u){
        if(u>n) return 0;
        if(mp.count(u)){
            auto p=mp[u];
            return max(p.first,p.second);
        }
        if(st.count(u)){
            int v1=u*2;
            int v2=u*2+1;
            if(st.count(v1)) return u+cal(v1);
            else return u+cal(v2);
        }
        return u+cal(u*2+1);
    }
    void init(){
        mp.clear();
        st.clear();
        int t=n;
        do{
            st.insert(t);
            t/=2;
        }while(t);
    }
    void update(int u, LL val){
        if(mp.count(u)==0){
            mp.emplace(u, make_pair(cal(u*2)+u,cal(u*2+1)+u));
            now[u]=u;
        }
        auto &p=mp[u];
        p.first+=val-now[u];
        p.second+=val-now[u];
        now[u]=val;
        int t=u;
        u/=2;
        while(u){
            if(mp.count(u)==0){
                mp.emplace(u, make_pair(cal(u*2)+u,cal(u*2+1)+u));
                now[u]=u;
            }
            else{
                auto &p2=mp[u];
                if(u*2==t){
                    p2.first=now[u]+cal(u*2);
                }
                else{
                    p2.second=now[u]+cal(u*2+1);
                }
            }
            u/=2;
            t/=2;
        }
    }
    LL query(int u){
        LL ans=0;
        if(mp.count(u)==0){
            mp.emplace(u,make_pair(u+cal(u*2),u+cal(u*2+1)));
            now[u]=u;
        }
        auto &p=mp[u];
        ans = p.first+p.second-now[u];
        LL len = max(p.first, p.second);
        int t=u;
        u/=2;
        while(u){
            if(mp.count(u)==0){
                mp.emplace(u,make_pair(cal(u*2)+u,cal(u*2+1)+u));
                now[u]=u;
            }
            auto &p=mp[u];
            if(u*2==t){
                ans=max(ans,p.second+len);
            }
            else{
                ans=max(ans,p.first+len);
            }
            len+=now[u];
            t/=2;
            u/=2;
        }
        return ans;
    }
    int main()
    {
        while(~scanf("%d%d", &n,&m))
        {
            init();
            for(int i=1; i<=m; i++){
                char op[10];
                scanf("%s", op);
                if(op[0] == 'q'){
                    int x;
                    scanf("%d", &x);
                    printf("%lld
    ", query(x));
                }
                else{
                    int x;
                    LL y;
                    scanf("%d%lld", &x,&y);
                    update(x,y);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Android Studio环境搭建
    JavaScript、Ajax与jQuery的关系
    Creational模式之Builder模式
    数据结构--二叉查找树的java实现
    ShopEx文章页添加上一篇下一篇功能
    WinCE的C#中使用StreamReader 来读取TXT文档,读取文本文档。
    关于对FLASH开发,starling、starling feathers、starling MVC框架的理解
    C语言实现牛顿迭代法解方程
    ios的notification机制是同步的还是异步的
    XCL-Chart柱形图的期望线/分界线
  • 原文地址:https://www.cnblogs.com/spfa/p/7418907.html
Copyright © 2020-2023  润新知