【点分治】luoguP2664 树上游戏

应该是一道中等难度的点分?麻烦在一些细节。

题目描述

lrb有一棵树,树的每个节点有个颜色。给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量。以及

现在他想让你求出所有的sum[i]

输入输出格式

输入格式:

第一行为一个整数n,表示树节点的数量

第二行为n个整数,分别表示n个节点的颜色c[1],c[2]……c[n]

接下来n-1行,每行为两个整数x,y,表示x和y之间有一条边

输出格式:

输出n行,第i行为sum[i]

说明

sum[1]=s(1,1)+s(1,2)+s(1,3)+s(1,4)+s(1,5)=1+2+3+2+2=10
sum[2]=s(2,1)+s(2,2)+s(2,3)+s(2,4)+s(2,5)=2+1+2+1+3=9
sum[3]=s(3,1)+s(3,2)+s(3,3)+s(3,4)+s(3,5)=3+2+1+2+3=11
sum[4]=s(4,1)+s(4,2)+s(4,3)+s(4,4)+s(4,5)=2+1+2+1+3=9
sum[5]=s(5,1)+s(5,2)+s(5,3)+s(5,4)+s(5,5)=2+3+3+3+1=12

对于40%的数据,n<=2000

对于100%的数据,1<=n,c[i]<=10^5


题目分析

想法一:按颜色拆贡献

这里应该是有一种小颜色大颜色的分块套路的。但是这个想法我只能解决全局路径的数量和,并不会落实到点的询问。

想法二:点分治

目前尚未归结出点分治适用的具体问题范围……不过这一题是可以用点分解决的。

考虑每一层点分树,我们只需要对它的节点处理贡献。这里的贡献分为两部分:重心答案;经过重心的路径对子树的贡献。

重心的答案只需要以它自身为根,遍历一边该层点分树即可。子树内的答案处理要略微麻烦一些,需要分颜色来考虑贡献。记$colCnt[i]$为所有以重心为起点的路径中,含有颜色$i$的路径条数。然后首先假定子树内所有点的答案都为$\sum colCnt[i]$,再容斥考虑重心到子树路径上的颜色所产生的贡献。

记当前点分树中除去正在处理的子树的大小为$outTot$,那么对于子树内点$x$,由于它具有颜色$c[x]$,所以对自身的答案有一个$outTot-colCnt[c[x]]$的贡献。并且,这一个贡献对于$x$的子树也是一概适用的,所以这一个标记要差分式地下传。

整体思路就是这些。这一题的点分涉及到例如“子树结构的重定向”或是“两个颜色桶并存”的一些细节问题,所以实现上面可能有一定的难度。

(话说这题的码风怎么这么丑)

 

  1 #include<bits/stdc++.h>
  2 typedef long long ll;
  3 const int maxn = 100035;
  4 const int maxm = 200035;
  5 
  6 ll ans[maxn];
  7 int n,bloTot,outTot,c[maxn]; 
  8 int size[maxn],son[maxn],root;
  9 int edgeTot,head[maxn],nxt[maxm],edges[maxm];
 10 int cols,cnt,cl,col[maxn],colTmp[maxn],colTim[maxn],colCnt[maxn],subCnt[maxn];
 11 bool colEx[maxn],divEx[maxn];
 12 
 13 int read()
 14 {
 15     char ch = getchar();
 16     int num = 0, fl = 1;
 17     for (; !isdigit(ch); ch=getchar())
 18         if (ch=='-') fl = -1;
 19     for (; isdigit(ch); ch=getchar())
 20         num = (num<<1)+(num<<3)+ch-48;
 21     return num*fl;
 22 }
 23 void addedge(int u, int v)
 24 {
 25     edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
 26     edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
 27 }
 28 void getRoot(int x, int fa)
 29 {
 30     size[x] = 1, son[x] = 0;
 31     for (int i=head[x]; i!=-1; i=nxt[i])
 32     {
 33         int v = edges[i];
 34         if (divEx[v]||v==fa) continue;
 35         getRoot(v, x), size[x] += size[v];
 36         son[x] = std::max(son[x], size[v]);
 37     }
 38     son[x] = std::max(son[x], bloTot-size[x]);
 39     if (son[x] < son[root]) root = x;
 40 }
 41 void colDfs(int x, int fa, int *cnt)
 42 {
 43     if (!colEx[c[x]]) colEx[c[x]] = 1, col[++cols] = c[x];
 44     if ((++colTim[c[x]])==1) cnt[c[x]] += size[x];
 45     for (int i=head[x]; i!=-1; i=nxt[i])
 46         if ((!divEx[edges[i]])&&(edges[i]!=fa))
 47             colDfs(edges[i], x, cnt);
 48     --colTim[c[x]];
 49 }
 50 void colClear()
 51 {
 52     for (int i=1; i<=cl; i++) colEx[colTmp[i]] = 0;
 53     cols = 0;
 54 }
 55 void modify(int x, int fa, ll tag)
 56 {
 57     if ((++colTim[c[x]])==1) tag += outTot-colCnt[c[x]];
 58     ans[x] += tag+cnt;
 59     for (int i=head[x]; i!=-1; i=nxt[i])
 60     {
 61         int v = edges[i];
 62         if (v==fa||divEx[v]) continue;
 63         modify(v, x, tag);
 64     }
 65     --colTim[c[x]];
 66 }
 67 void calc(int rt)      //核心操作在这里
 68 {
 69     colClear(), getRoot(rt, 0);
 70     colDfs(rt, 0, colCnt);
 71     cnt = 0, cl = cols;
 72     for (int i=1; i<=cols; i++)
 73         cnt += colCnt[col[i]], colTmp[i] = col[i];
 74     ans[rt] += cnt;
 75     for (int i=head[rt]; i!=-1; i=nxt[i])
 76     {
 77         int v = edges[i];
 78         if (divEx[v]) continue;
 79         for (int j=1; j<=cl; j++) subCnt[colTmp[j]] = 0;  //及时清除数组
 80         colClear();
 81         colEx[c[rt]] = 1;
 82         colDfs(v, rt, subCnt);          //统计子树内的含颜色i路径条数
 83         colEx[c[rt]] = 0;
 84         colCnt[c[rt]] -= size[v], cnt -= size[v];   //除去重心出发的路径
 85         for (int j=1; j<=cols; j++)
 86         {
 87             colCnt[col[j]] -= subCnt[col[j]];  //除去子树内的路径(因为考虑子树外路径)
 88             cnt -= subCnt[col[j]];
 89         }
 90         outTot = size[rt]-size[v], modify(v, rt, 0);  //对子树内累加贡献
 91         colCnt[c[rt]] += size[v], cnt += size[v];    //恢复处理子树前状态
 92         for (int j=1; j<=cols; j++)
 93         {
 94             colCnt[col[j]] += subCnt[col[j]];
 95             cnt += subCnt[col[j]];
 96         }
 97     }
 98     for (int i=1; i<=cl; i++)
 99         colCnt[colTmp[i]] = 0;      //colTmp[]的作用;清空colCnt[]
100 }
101 void deal(int rt)
102 {
103     calc(rt), divEx[rt] = 1;
104     for (int i=head[rt]; i!=-1; i=nxt[i])
105     {
106         int v = edges[i];
107         if (divEx[v]) continue;
108         root = 0, bloTot = size[v];
109         getRoot(v, 0), deal(root);
110     }
111 }
112 int main()
113 {
114     memset(head, -1, sizeof head);
115     n = read(), son[0] = n;
116     for (int i=1; i<=n; i++) c[i] = read();
117     for (int i=1; i<n; i++) addedge(read(), read());
118     bloTot = n, getRoot(1, 0), deal(root);
119     for (int i=1; i<=n; i++) printf("%lld\n",ans[i]);
120     return 0;
121 }

 

 

 

END

转载于:https://www.cnblogs.com/antiquality/p/10339899.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/387494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EasyJoyStick使用以及两种操作杆 EasyJoyStick的使用方法,简单的不能再简单 Hedgehog Team-》Easy Touch -》Add Easy Touch For C#

EasyJoyStick使用以及两种操作杆EasyJoyStick的使用方法&#xff0c;简单的不能再简单Hedgehog Team-》Easy Touch -》Add Easy Touch For C#Hedgehog Team-》Easy Touch -》Extensions-》Adding A New Joystick配置如图&#xff1a;然后看一下配置&#xff0c;我喜欢掌控性强一…

Web渗透实验:基于Weblogic的一系列漏洞

1. 攻击机windows10 192.168.2.104 2. 靶机ip: 192.168.2.109(linux Ubantu) 192.168.2.111(windows2008R264位) 第一步&#xff1a;启动靶机服务 分别为linux和windows windows环境搭建&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/16KyYb1v1rP9uJ6-5MBotVw   提取…

Unity3D 自动打包整个项目(以AssetBundle实现)

需求&#xff1a; 在移动开发中&#xff0c;手动控制资源的加载、释放和热更新&#xff0c;是很有必要的。 而Unity通过AssetBundle可以实现该需求&#xff0c;但是如果项目资源多起来的话一个个手动打包成AssetBundle则很麻烦。 而本文正为此提供一套一键打包的方案。 资源分…

Python 2.7 cython cythonize py 编译成 pyd 谈谈那些坑(转载)

转自&#xff1a;https://www.cnblogs.com/ibingshan/p/10334471.html Python 2.7 cython cythonize py 编译成 pyd 谈谈那些坑 前言 基于 python27 的 pyc 很容易被反编译&#xff0c;于是想到了pyd&#xff0c;加速运行&#xff0c;安全保护 必要准备 安装cython&#xff1a;…

一、创建Assetbundle 在unity3d开发的游戏中,无论模型,音频,还是图片等,我们都做成Prefab,然后打包成Assetbundle,方便我们后面的使用,来达到资源的更新。

一、创建Assetbundle 在unity3d开发的游戏中&#xff0c;无论模型&#xff0c;音频&#xff0c;还是图片等&#xff0c;我们都做成Prefab&#xff0c;然后打包成Assetbundle&#xff0c;方便我们后面的使用&#xff0c;来达到资源的更新。 一个Assetbundle可以打包一个模型&…

【JS】我的JavaScript学习之路(2)

3.从JavaScript页面解析过程看执行顺序 代码(test.html)&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/x…

王者荣耀提取攻略

1. 王者荣耀安装后&#xff0c;就将模型等资源解压到SD卡目录里&#xff0c;我们需要找到这个目录。模型资源存储在SD卡中&#xff0c;路径为&#xff1a;【/SDCard/Android/data/com.tencent.tmgp.sgame/files/Resources/AssetBundle/】 2. 2 所有英雄的资源包都在这个目…

Exchange ActiveSyn身份验证类型

http://www.exchangecn.com/html/exchange2010/20110125_316.html 配置 Exchange ActiveSync 身份验证 时间:2011-01-25 11:01来源:Exchange中文站 作者:Exchange中文站 点击:3045次ActiveSync 身份验证是客户端和服务器验证其身份以进行数据传输的过程&#xff0c;本文以示例的…

二 SVN代码冲突的解决

问题&#xff1a; A和B都是最新的代码&#xff0c;A修改了代码提交了&#xff0c;B也修改了代码&#xff0c;但是B提交的时候出现冲突的问题。 解决方案&#xff1a;编辑冲突 解决冲突&#xff1a; 方法一&#xff1a;将文件里面冲突的描述去掉&#xff0c;重新提交 方法二&…

Android7.0反射类找不到的问题

Java中使用反射的地方较多&#xff0c;尤其是各种框架中。最近在Android7.0的项目中遇到个问题很奇怪&#xff0c;反射使用的类找不到了&#xff0c;但是编译的时候没问题啊。然后在代码中使用非反射的方式调用代码也是没有问题的&#xff0c;这时奇怪的现象出现了&#xff0c;…

[转]JSon数据解析的四种方式

转至http://blog.csdn.net/enuola/article/details/7903632 作为一种轻量级的数据交换格式&#xff0c;json正在逐步取代xml&#xff0c;成为网络数据的通用格式。 有的json代码格式比较混乱&#xff0c;可以使用此“http://www.bejson.com/”网站来进行JSON格式化校验&#xf…

iOS开发UI篇—Quartz2D使用(绘图路径)

1 //1.获取图形上下文 2 CGContextRef ctxUIGraphicsGetCurrentContext(); 3 //2.绘图&#xff08;画线&#xff09; 4 //设置起点 5 CGContextMoveToPoint(ctx, 20, 20); 6 //设置终点 7 CGContextAddLineToPoint(ctx, 200, 300); 8 //渲染 9…

13结构型模式之桥接模式

概念 Bridge 模式又叫做桥接模式&#xff0c;是构造型的设计模式之一。Bridge模式基于类的最小设计原则&#xff0c;通过使用封装&#xff0c;聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象&#xff08;abstraction&#xff09;与行为实现&#xff08;i…

简易中控紫猫插件版(3)压缩包使用说明

1.环境配置脚本运行环境&#xff1a;没什么说的 正常的最新版手机按键 当然还需要 最新的紫猫插件中控运行环境&#xff1a;首先要保证把压缩包的所有php文件都扔到网站的根目录下 必须保证网站的php版本是5.4 不然紫猫插件的php框架会出问题 然后你要知道网站数据库的账号和密…

Java9新特性

Java 8 发布三年多之后&#xff0c;即将快到2017年7月下一个版本发布的日期了。 你可能已经听说过 Java 9 的模块系统&#xff0c;但是这个新版本还有许多其它的更新。 这里有九个令人兴奋的新功能将与 Java 9 一起发布。 1. Java 平台级模块系统 Java 9 的定义功能是一套全新的…

Java面试常见算法

在程序员的职业生涯中&#xff0c;算法亦算是一门基础课程&#xff0c;尤其是在面试的时候&#xff0c;很多公司都会让程序员编写一些算法实例&#xff0c;例如快速排序、二叉树查找等等。 本文总结了程序员在代码面试中最常遇到的10大算法类型&#xff0c;想要真正了解这些算法…

高仿人人Android梦想版终极源码发送(转)

经过几个月的努力,终于基本完成了人人API拥有的所有功能,界面采用仿照人人梦想版5.13制作,其中资源文件也采用人人的APK文件资源,完成的功能及知识点如下:1.通过三种动画仿照出人人引导页的放大切换图片的效果。2.通过重写ViewGroup仿照出人人菜单和其他界面的手势滑动切换效果…

android 实现SSL握手协商

Android的私钥和信任证书的格式必须是BKS格式的&#xff0c;通过配置本地JDK&#xff0c;让keytool可以生成BKS格式的私钥和信任证书,java本身没有BouncyCastle密库 ssl通道建立前必须进行协商&#xff08;形成安全的通道--隧道技术&#xff09;。 服务端&#xff1a; View Co…

同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO

IO的方式通常分为几种&#xff0c;同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。 一、BIO 在JDK1.4出来之前&#xff0c;我们建立网络连接的时候采用BIO模式&#xff0c;需要先在服务端启动一个ServerSocket&#xff0c;然后在客户端启动Socket来对服务端进行通信&#x…

1 概述

Unix C TCP/IP 三位一体 Linux天生是网络操作系统 程序员的学习&#xff1a;不断地敲代码&#xff0c;不断地看别人的代码。 Linux两大领域&#xff1a; &#xff08;1&#xff09;服务器 &#xff08;2&#xff09;嵌入式设备 www.netcraft.com 查看网站服务器系统 VMware快…