题目大意:

给定n个点的无根树,树上每个点都有一个非负的点权.

树上的路径的价值定义为树上路径的点权和-树上路径的点权最大值;

现在给定一个参数P询问有多少条路径的价值是P的倍数(注意单点也算路径,路径不重复算)

这个题一眼就知道是点分治之类的鬼东西,第一眼觉得长得想聪聪可可,然后直接开了一个桶码起点分治,

但是有一个尴尬的地方就是在处理经过一个点的路径的时候我发现我不知道该怎么O(size)的转移,因为路径

上的最大值是不知道的,所以我考场上只打一个O(size^2)的转移(暴力枚举组合...),于是复杂度变成了n^2*logn

还不如n^2暴力...于是实力滚粗

好吧,我们想一想我们处理这个问题的瓶颈就是如何处理经过一个点的路径

我们又发现这个问题的瓶颈是处理这个max,由于不知道max所以我们只能暴力枚举组合

于是冥冥中我就蠢了,听大佬讲题的第一句话就想把自己的脸打肿

我们考虑让max变的有序起来

比如说我们把一这个点为根能遍历到的点按照max从小到达sort再依次加入与已有的边进行组合

这样有什么好处呢???

我们发现这样你每把当前这条边加入和原来的边进行组合的时候,由于已经按max排过序了,

他和别的边组合的max,就是他自己的max,这样组合的max的边就已知了,

这样你就可以直接查询桶了,然后加完后再把他自己的权值和放入桶中,和聪聪可可有点像

复杂度n*logn^2;

这题嘴巴AC很容易,但是由于他记的是点权,所以在处理的时候需要一些不同于边权的操作,所以在

摸爬滚打很久之后才AC

附上代码:

// MADE BY QT666
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<queue>
#include<set>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#define lson num<<1
#define rson num<<1|1
#define int long long
using namespace std;
typedef long long ll;
const int N=300050;
const int Inf=2147483647;
int gi()
{
int x=0,flag=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
int head[N],nxt[N],to[N],P,n,ans;
int size[N],f[N],dis[N],maxn[N],vis[N];
int root,SIZE,v[N],tot,cnt,tong[10000050],used[N];
struct data{
int dis,maxn,id;
}w[N];
bool cmp(const data & a,const data &b){
return a.maxn<b.maxn;
}
void getroot(int x,int fa){
size[x]=1;f[x]=0;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y!=fa&&!vis[y]){
getroot(y,x);
size[x]+=size[y];
f[x]=max(f[x],size[y]);
}
}
f[x]=max(f[x],SIZE-size[x]);
if(f[x]<f[root]) root=x;
}
void getdeep(int x,int fa){
w[++tot]=(data){dis[x],maxn[x],x};
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(y!=fa&&!vis[y]){
dis[y]=(dis[x]+v[y])%P;
maxn[y]=max(maxn[x],v[y]);
getdeep(y,x);
}
}
}
int cal(int x,int y){
int ret=0,sum=0,tt=0;
tot=0;dis[x]=(v[x]+y)%P,maxn[x]=max(v[x],y);
getdeep(x,0);sort(w+1,w+1+tot,cmp);
//if(y) cout<<"是要减去的"<<' ';
//cout<<x<<"的子树中:"<<endl;
if(y==0) y=v[x];
for(int i=1;i<=tot;i++){
//cout<<w[i].dis<<' '<<w[i].maxn<<' '<<w[i].id<<"need:";
int now=(P+w[i].maxn+y-w[i].dis)%P;
//cout<<now<<' '<<tong[now]<<endl;
ret+=tong[now];
tong[w[i].dis]++;
used[++sum]=w[i].dis;
}
//cout<<"产生"<<ret<<"的贡献"<<endl;
//cout<<"---------"<<endl;
for(int i=1;i<=sum;i++) tong[used[i]]--;
return ret;
}
void work(int x){
ans+=cal(x,0);vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int y=to[i];
if(!vis[y]){
ans-=cal(y,v[x]);
SIZE=size[y];root=0;
getroot(y,root);work(root);
}
}
}
void lnk(int x,int y){
to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
}
main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
n=gi(),P=gi();
for(int i=1;i<n;i++){
int x=gi(),y=gi();lnk(x,y);
}
for(int i=1;i<=n;i++) v[i]=gi();
root=0;f[0]=Inf;SIZE=n;getroot(1,0);work(root);ans+=n;
printf("%lld\n",ans);
}

某次送温暖考试的 c题的更多相关文章

  1. bzoj4693: 雪中送温暖

    Description 每年的1月10日是温暖节,在这一天,化身出题人的C_SUNSHINE将会给OIer们送温暖.OIer们只要在门口放上一个 仙人掌,就能在早上的某个时刻听到门外传来一声:“开门, ...

  2. 中国MOOC_零基础学Java语言_期末考试的编程题_1二进制的前导的零

    期末考试的编程题 返回   这是期末考试的编程题,在60分钟内,你可以多次提交,直到正确为止. 温馨提示: 1.本次考试属于Online Judge题目,提交后由系统即时判分. 2.学生可以在考试截止 ...

  3. 考试宝典-真题园安卓AppV2.1.0新版发布啦,全新界面,全新体验,全面适配Android 5.0&6.0系统!

    真题园移动客户端是真题园网 http://www.zhentiyuan.com 旗下的一款学习考试应用App. 1.全新适配Android5.0.6.0系统,重新优化架构网络通信模块. 2.全新清爽U ...

  4. C语言考试解答十题

    学院比较奇葩,大一下期让学的VB,这学期就要学C++了,然后在开学的前三个周没有课,就由老师讲三个周的C语言,每天9:30~11:30听课,除去放假和双休日,实际听课时间一共是12天*2小时,下午是1 ...

  5. OCP 认证考试报名费技巧题库051052053解析合格线

    本人于2017年4月22日通过参加OCP考试,第一次参加,一天之内考了三门,三门一次性通过,052 - 95% ,053 - 86% ,051 - 100% 一.关于考试考试报名费: 052:158$ ...

  6. HDU 2093 考试排名 模拟题

    解题报告: 题目描述:写一个程序给一个编程考试C++实时提交系统排名,给你的数据是题目的总数,每次错误提交罚的时间分,每位用户的姓名,然后是输入用户每题的完成情况,有一下几种情况,第一,输入只有一个正 ...

  7. 2019PAT春季考试第4题 7-4 Structure of a Binary Tree (30 分)

    题外话:考试的时候花了一个小时做了27分,由于Siblings这个单词不知道意思,所以剩下的3分就没去纠结了,后来发现单词是兄弟的意思,气哭~~ 这道题的麻烦之处在于如何从一个字符串中去找数字.先首先 ...

  8. [考试]NOIP2015模拟题2

    // 此博文为迁移而来,写于2015年7月22日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w72i.html 1.总 ...

  9. [HNOI2009]双递增序列(洛谷P4728)+小烈送菜(内部训练题)——奇妙的dp

    博主学习本题的经过嘤嘤嘤: 7.22 : 听学长讲(一知半解)--自己推(推不出来)--网上看题解--以为自己会了(网上题解是错的)--发现错误以后又自己推(没推出来)--给学长发邮件--得到正确解法 ...

随机推荐

  1. Mysql语句查询优化

    其实对Mysql查询语句进行优化是一件非常有必要的事情. 如何查看当前sql语句的执行效率呢? 1.建一张学生表 CREATE TABLE `student` ( `stu_id` ) NOT NUL ...

  2. BST 解析 (一)

    这篇博文主要初步介绍Binary Search Tree(BST)的一些基本功能以及应用场景,由于BST的相关知识比较多,下一节会接着补充BST的一些功能.这一节主要分为以下三个要素: BST 的定义 ...

  3. 常用的redis命令

      常用的redis命令 http://www.runoob.com/redis/redis-tutorial.html 菜鸟教程   Cmd连接有密码的redis:$ redis-cli -h ho ...

  4. Android 异步消息处理机制前篇(二):深入理解Message消息池

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 上一篇中共同探讨了ThreadLocal,这篇我们一起看下常提到的Message消息池到底是怎么回事,废话少说吧,进入正题. 对于稍有经验的开发人员 ...

  5. 实际应用中遇到TimedRotatingFileHandler不滚动的问题

    需求: 程序每天晚上8点和10点定时运行,期望日志按日期记录 添加Handler部分代码如下: formatter = logging.Formatter("%(asctime)s %(fi ...

  6. Js特殊字符转义之htmlEscape()方法

    为了防止XSS攻击,常常需要将用户输入的特殊字符进行转义,原生js貌似还没有直接对其专业的方法,最近再读Js高级程序设计的时候刚好看到,碰巧项目中也刚好需要使用次方法,于是就之家搬来用了. 网上关于转 ...

  7. PHP大文件分割上传(分片上传)

    服务端为什么不能直接传大文件?跟php.ini里面的几个配置有关 upload_max_filesize = 2M //PHP最大能接受的文件大小 post_max_size = 8M //PHP能收 ...

  8. 数据结构与算法(C/C++版)【栈与队列】

    第三章<栈与队列> (一)栈简介  栈(Stack):只允许在一端进行插入或删除操作的线性表.首先栈是一种线性表,但是限定这种线性表只能在某一端进行插入和删除操作栈顶(top):线性表允许 ...

  9. Elasticsearch JAVA api搞定groupBy聚合

    本文给出如何使用Elasticsearch的Java API做类似SQL的group by聚合.为了简单起见,只给出一级groupby即group by field1(而不涉及到多级,例如group ...

  10. Kotlin 一个好用的新功能:Parcelize

    在开发中,如果有需要用到序列化和反序列化的操作,就会用到 Serializable 或者 Parcelable,它们各有优缺点,会适用于不同的场景. Serializable 的优点是实现简单,你只需 ...