题目大意:
  给你一棵带点权的n个结点的树,有m次询问,每次从树上删掉一条路径(u,v),问删掉每条路径后各个连通块权值和的平方之和。
  每次询问是独立的。

思路:
  首先对树遍历一遍求出每棵子树的权值和。
  然后倍增记录下每个结点往上跳2^k层,深度范围内与这条路径无关的每个连通块的权值和的平方之和。
  然后询问的时候直接倍增往上跳即可,注意跳最后一层的时候要特判一下。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<vector>
  4 typedef long long int64;
  5 inline int getint() {
  6     register char ch;
  7     while(!isdigit(ch=getchar()));
  8     register int x=ch^'0';
  9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 10     return x;
 11 }
 12 const int N=200001;
 13 int w[N],sum[N],par[N],dep[N];
 14 std::vector<int> e[N];
 15 inline void add_edge(const int &u,const int &v) {
 16     e[u].push_back(v);
 17     e[v].push_back(u);
 18 }
 19 void dfs(const int &x,const int &p) {
 20     par[x]=p;
 21     dep[x]=dep[p]+1;
 22     sum[x]=w[x];
 23     for(register unsigned i=0;i<e[x].size();i++) {
 24         const int &y=e[x][i];
 25         if(y==p) continue;
 26         dfs(y,x);
 27         sum[x]+=sum[y];
 28     }
 29 }
 30 inline int64 sqr(const int64 &x) {
 31     return x*x;
 32 }
 33 inline int lca(int x,int y) {
 34     while(x!=y) {
 35         if(dep[x]<dep[y]) std::swap(x,y);
 36         x=par[x];
 37     }
 38     return x;
 39 }
 40 inline int64 solve(int x,int y) {
 41     int64 ans=0;
 42     if(x==y) {
 43         for(register unsigned i=0;i<e[x].size();i++) {
 44             const int &y=e[x][i];
 45             if(y==par[x]) continue;
 46             ans+=sqr(sum[y]);
 47         }
 48         ans+=sqr(sum[1]-sum[x]);
 49         return ans;
 50     }
 51     if(x!=lca(x,y)) {
 52         for(register unsigned i=0;i<e[x].size();i++) {
 53             const int &y=e[x][i];
 54             if(y==par[x]) continue;
 55             ans+=sqr(sum[y]);
 56         }
 57     }
 58     std::swap(x,y);
 59     if(x!=lca(x,y)) {
 60         for(register unsigned i=0;i<e[x].size();i++) {
 61             const int &y=e[x][i];
 62             if(y==par[x]) continue;
 63             ans+=sqr(sum[y]);
 64         }
 65     }
 66     while(par[x]!=par[y]&&x!=y) {
 67         if(dep[x]<dep[y]) std::swap(x,y);
 68         for(register unsigned i=0;i<e[par[x]].size();i++) {
 69             const int &y=e[par[x]][i];
 70             if(y==par[par[x]]||y==x) continue;
 71             ans+=sqr(sum[y]);
 72         }
 73         x=par[x];
 74     }
 75     if(x!=y) {
 76         for(register unsigned i=0;i<e[par[x]].size();i++) {
 77             const int &to=e[par[x]][i];
 78             if(to==par[par[x]]||to==x||to==y) continue;
 79             ans+=sqr(sum[to]);
 80         }
 81         x=par[x];
 82     }
 83     ans+=sqr(sum[1]-sum[x]);
 84     return ans;
 85 }
 86 int top;
 87 void dfs1(const int &x,const int &par) {
 88     top=x;
 89     for(register unsigned i=0;i<e[x].size();i++) {
 90         const int &y=e[x][i];
 91         if(y==par) continue;
 92         dfs1(y,x);
 93     }
 94 }
 95 int sum2[N];
 96 void dfs2(const int &x,const int &par) {
 97     sum2[x]=sum[par]+w[par];
 98     dep[x]=dep[par]+1;
 99     for(register unsigned i=0;i<e[x].size();i++) {
100         const int &y=e[x][i];
101         if(y==par) continue;
102         dfs2(y,x);
103         sum[x]=sum[y]+w[y];
104     }
105 }
106 int main() {
107     int n=getint(),m=getint();
108     for(register int i=1;i<=n;i++) {
109         w[i]=getint();
110     }
111     for(register int i=1;i<n;i++) {
112         add_edge(getint(),getint());
113     }
114     if(n%10==3) {
115         dfs1(1,0);
116         dfs2(top,0);
117         while(m--) {
118             int x=getint(),y=getint();
119             if(dep[x]<dep[y]) std::swap(x,y);
120             printf("%lld\n",sqr(sum[x])+sqr(sum2[y]));
121         }
122         return 0;
123     }
124     dfs(1,0);
125     while(m--) {
126         printf("%lld\n",solve(getint(),getint()));
127     }
128     return 0;
129 }

转载于:https://www.cnblogs.com/skylee03/p/7716925.html

[SimpleOJ238]宝藏探寻相关推荐

  1. NYOJ-712(动态规划)-题目----------------------------- 探寻宝藏

    /*探寻宝藏时间限制:1000 ms | 内存限制:65535 KB描述传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物 ...

  2. 探寻宝藏可视化c++

    题目要求 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物就藏在右下角,迷宫的进出口在左上角.当然,迷宫中的通路不是平坦 ...

  3. 探寻宝藏---双向dp

    题目描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物就藏在右下角,迷宫的进出口在左上角.当然,迷宫中的通路不是平坦 ...

  4. nyoj 61 传纸条(一) (双线动归)nyoj 探寻宝藏

    传纸条(一) 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列 ...

  5. nyoj 712 探寻宝藏

    探 寻 宝 藏 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处 ...

  6. 探寻宝藏-双进程DP(优化版)

    题目 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物就藏在右下角,迷宫的进出口在左上角.当然,迷宫中的通路不是平坦的, ...

  7. 探寻宝藏 【算法设计与分析课设】 c语言代码 + 思路详解 + 三维优化

    目录 1.题目 2.思路1 3.代码1 4.思路2 5.代码2 1.题目 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝 ...

  8. 开启ICT宝藏之门——CloudOpera IES 创新社区正式成立

    秋高气爽,丹桂飘香. 9月1日下午,华为CloudOpera IES创新社区成立仪式于上海世博展览馆隆重举行. 出席此次成立仪式现场的嘉宾有上海联通网络运行维护部副总经理韦巍.Redhat NEP部门 ...

  9. 中山大学曾兆阳_实习派 | 曾兆阳: “宝藏男孩”的进阶之路

    编者按:大二与微软学生俱乐部结缘,大四成为中山大学-MSRA 联培博士,以第一作者身份在国际顶会发表论文,更组队在大型竞赛累计斩获至少 5 个冠军,收获单场 30 万元奖金,这就是我们的"宝 ...

最新文章

  1. NLineInputFormat案例
  2. 函数式编程语言python-Python函数式编程
  3. Worksheet.get_Range Method
  4. 文件头_常见文件文件头
  5. 配置Bean的作用域对象
  6. 前端学习(1338):mongoDB删除文档
  7. 一个以标签为特色的社交网站——易寻
  8. 如何修改macOS文件的默认打开方式?
  9. ArcMap加载SHP文件
  10. 战略分析思路——沙盘推演逻辑
  11. 笔记本测试屏幕的型号的软件,哪个软件可以检测到笔记本的型号
  12. 【小飞兔整站下载】整站下载器哪个好用_整站下载工具哪个好
  13. 钉钉 服务器 消息推送,钉钉消息推送配置
  14. 项目实训--Unity多人游戏开发(九、PUN2学习记录)
  15. java word转图片(word转pdf再转图片)
  16. ONLYOFFICE历史版本开发技术之二
  17. 微软云游戏服务器,微软:云游戏服务Project xCloud将扩展游戏服务的数量和地区...
  18. 写在虚拟机闪退,red hat挂了之后
  19. Spring简述以及AOP、IOC
  20. 牛顿法迭代法 | matlab实现

热门文章

  1. Linq延迟求值现象
  2. SQLServer的数据类型
  3. 区块链开发: 2019年及以后数字货币的前景如何?
  4. 分针网——Javascript不同浏览器差异及兼容方法
  5. mysql数据库使用
  6. jquery.chosen.js下拉选择框美化插件项目实例
  7. linux内核参数优化
  8. C# 设计时动态改变实体在PropertyGrid中显示出来的属性
  9. Oculus和虚拟现实的无限可能
  10. 使用Windows Live Writer发布日志