题目大意:

给定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. 加密代理和Retrofit解密Converter

    最近在研究安卓的Retrofit框架,服务器的数据全部用加密算法加密了,发现无法使用"com.squareup.retrofit2:converter-gson:2.1.0"Jar ...

  2. LDA算法入门

    http://blog.csdn.net/warmyellow/article/details/5454943 LDA算法入门 一. LDA算法概述: 线性判别式分析(Linear Discrimin ...

  3. Unity塔防游戏开发

    Unity3D塔防开发流程 配置环境及场景搭建编程语言:C#,略懂些许设计模式,如果不了解设计模式,BUG More开发工具:Unity3D编辑器.Visual Studio编译器开发建议:了解Uni ...

  4. 51Nod--1085背包问题

    1085 背包问题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2--Wn(Wi为整 ...

  5. ACM HDU 1081 To The Max

     To The Max Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) To ...

  6. 生成pdf

    /** * 生成pdf * @param string $html 需要生成的内容 */ function pdf($html='<h1 style="color:red"& ...

  7. mysql中 union是什么鬼

    在sql注意时,经常会用到一个不怎么常用的联合查询 http://www.php20.com/forum.php?m ... &extra=page%3D1 清空表.从新执行一下以上链接中的s ...

  8. MySQL之事务的四大特性

    事务就是一组原子性的SQL查询,或者说一个独立的工作单元.如果数据库引擎能够成功地对数据应用该组查询的全部语句,那么久执行该组查询.如果其中任何一条语句因为崩溃或其他原因无法执行,那么所有语句都不会执 ...

  9. JS 转换数字为大写

    function toUpper(n) { n = n+''; var unit = '十百千万'; var num = '一二三四五六七八九 '; var array = new Array(); ...

  10. C语言递归实现二叉树(二叉链表)的三种遍历和销毁操作(实验)

    今天写的是二叉树操作的实验,这个实验有三个部分: ①建立二叉树,采用二叉链表结构 ②先序.中序.后续遍历二叉树,输出节点值 ③销毁二叉树 二叉树的节点结构定义 typedef struct BiTNo ...