题目:https://www.luogu.org/problemnew/show/P4178

点分治。如果把每次的 dis 和 K-dis 都离散化,用树状数组找,是O(n*logn*logn),会T7个点。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=4e4+5;
int n,hd[N],xnt,to[N<<1],nxt[N<<1],w[N<<1],f[N<<1],siz[N],ans,mn,rt;
ll dis[N],tis[N],tp[N<<1],tnt,K;
bool vis[N],sj[N];
void add(int x,int y,ll z)
{to[++xnt]=y;nxt[xnt]=hd[x];w[xnt]=z;hd[x]=xnt;to[++xnt]=x;nxt[xnt]=hd[y];w[xnt]=z;hd[y]=xnt;
}
void getrt(int cr,int fa,int s)
{siz[cr]=1;int mx=0;for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa){getrt(v,cr,s);siz[cr]+=siz[v];mx=max(mx,siz[v]);}mx=max(mx,s-siz[cr]);if(mx<mn)mn=mx,rt=cr;
}
void add(int x){for(;x<=tnt;x+=(x&-x))f[x]++;}
int query(int x){int ret=0;for(;x;x-=(x&-x))ret+=f[x];return ret;}
void dfs(int cr,int fa,ll lj)
{dis[cr]=lj;sj[cr]=1;for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)dfs(v,cr,lj+w[i]);
}
int calc(int cr,ll w)
{memset(sj,0,sizeof sj);tnt=0;dfs(cr,0,w);for(int i=1;i<=n;i++) if(sj[i]&&dis[i]<=K){tis[i]=K-dis[i];tp[++tnt]=dis[i];tp[++tnt]=tis[i];
//        printf("dis[%d]=%lld tis[%d]=%lld\n",i,dis[i],i,tis[i]);
    }sort(tp+1,tp+tnt+1);tnt=unique(tp+1,tp+tnt+1)-tp-1;int ret=0;for(int i=1;i<=n;i++) if(sj[i]&&dis[i]<=K){dis[i]=lower_bound(tp+1,tp+tnt+1,dis[i])-tp;tis[i]=lower_bound(tp+1,tp+tnt+1,tis[i])-tp;
//        printf("dis[%d]=%lld tis[%d]=%lld\n",i,dis[i],i,tis[i]);ret+=query(tis[i]);add(dis[i]);}memset(f,0,sizeof f);return ret;
}
void solve(int cr,int s)
{
//    printf("rt=%d\n",cr);vis[cr]=1;ans+=calc(cr,0);
//    printf("cr=%d ans=%d\n",cr,ans);for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]){ans-=calc(v,w[i]);int ts=(siz[cr]>siz[v]?siz[v]:s-siz[cr]);//-siz[cr]!!!mn=N;getrt(v,0,ts);solve(rt,ts);}
}
int main()
{scanf("%d",&n);int x,y;ll z;for(int i=1;i<n;i++){scanf("%d%d%lld",&x,&y,&z);add(x,y,z);}scanf("%lld",&K);mn=N;getrt(1,0,n);solve(rt,n);printf("%d\n",ans);return 0;
}

View Code

应当排序后枚举两个指针。(代码中两种方法时间一样)

如果把 ts=s-siz[cr] 写成 ts=s-siz[v] ,就会T7个点(?)!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=4e4+5;
int n,hd[N],xnt,to[N<<1],nxt[N<<1],w[N<<1],siz[N],mn,rt,sta[N],top,K,ans;
bool vis[N];
void add(int x,int y,int z)
{to[++xnt]=y;nxt[xnt]=hd[x];w[xnt]=z;hd[x]=xnt;to[++xnt]=x;nxt[xnt]=hd[y];w[xnt]=z;hd[y]=xnt;
}
void getrt(int cr,int fa,int s)
{siz[cr]=1;int mx=0;for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa){getrt(v,cr,s);siz[cr]+=siz[v];mx=max(mx,siz[v]);}mx=max(mx,s-siz[cr]);if(mx<mn)mn=mx,rt=cr;
}
void dfs(int cr,int fa,int lj)
{sta[++top]=lj;for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]&&v!=fa)dfs(v,cr,lj+w[i]);
}
int calc(int cr,int w)
{int ret=0;dfs(cr,0,w);
//    l=1;r=0;
//    sort(sta+l,sta+r+1);
//    while(l<=r)
//        if(sta[l]+sta[r]<=K)ret+=r-l,l++;
//        else r--;sort(sta+1,sta+top+1);int p=top;for(int i=1;i<=top;i++){while(sta[p]+sta[i]>K&&p)p--;if(!p)break;ret+=p-(p>=i);}top=0;
//    printf("cr=%d ret=%d\n",cr,ret);return ret>>1;
}
void solve(int cr,int s)
{
//    printf("rt=%d\n",cr);vis[cr]=1;ans+=calc(cr,0);
//    printf("cr=%d ans=%d\n",cr,ans);for(int i=hd[cr],v;i;i=nxt[i]) if(!vis[v=to[i]]){ans-=calc(v,w[i]);int ts=(siz[cr]>siz[v]?siz[v]:s-siz[cr]);//s-siz[cr]!!!mn=N;getrt(v,0,ts);solve(rt,ts);}
}
int main()
{scanf("%d",&n);for(int i=1,x,y,z;i<n;i++){scanf("%d%d%d",&x,&y,&z);add(x,y,z);}scanf("%d",&K);mn=N;getrt(1,0,n);solve(rt,n);printf("%d\n",ans);return 0;
}

转载于:https://www.cnblogs.com/Narh/p/9478066.html

洛谷 4178 Tree——点分治相关推荐

  1. 洛谷T44252 线索_分治线段树_思维题

    分治线段树,其实就是将标记永久化,到最后再统一下传所有标记. 至于先后顺序,可以给每个节点开一个时间戳. 一般地,分治线段树用于离线,只查询一次答案的题目. 本题中,标记要被下传 222 次. Cod ...

  2. 洛谷 P1498 南蛮图腾 分治递归过程详解

    题目描述 自从到了南蛮之地,孔明不仅把孟获收拾的服服帖帖,而且还发现了不少少数民族的智慧,他发现少数民族的图腾往往有着一种分形的效果,在得到了酋长的传授后,孔明掌握了不少绘图技术,但唯独不会画他们的图 ...

  3. 洛谷 P2400 秘密文件【分治】

    ... 题目: 题意: 分析: 代码: 题目: 传送门 题意: 给出一个较长的字符串,要求我们按照规则进行化简,使得其长度最短 分析: 直接使用分治的思想,对于区间l−rl-rl−r,我们枚举一个分界 ...

  4. 洛谷 4115 Qtree4——链分治

    题目:https://www.luogu.org/problemnew/show/P4115 论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb ...

  5. [WC2005]双面棋盘,洛谷P4121,线段树分治+可撤销并查集

    正题 这题主要是来练手的,因为没写过可撤销的并查集,大概就是把每一个格子看成一个点,然后格子直接的边有很多的出现区间,把这些出现区间和对应的颜色打到线段树上,然后用可撤销的并查集来维护就可以了. #i ...

  6. 【洛谷习题】南蛮图腾

    题目链接:https://www.luogu.org/problemnew/show/P1498 不好实现... 这道题在洛谷的分类是分治,我用的方法就是分治,不过却刷新的我对分治的认识.以前见过的分 ...

  7. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

  8. 分治——Secret Cow Code S(洛谷 P3612)

    题目选自洛谷P3612 梳理题意 给定一个字符串,每次将其最后一个字符移到最前方,形成的新串接到原串后作为下一次操作的字符串 现询问第 N 个位置的字符 简要分析 看一眼数据范围,N<10^18 ...

  9. BZOJ4553/洛谷P4093 [HEOI2016/TJOI2016]序列 动态规划 分治

    原文链接http://www.cnblogs.com/zhouzhendong/p/8672434.html 题目传送门 - BZOJ4553 题目传送门 - 洛谷P4093 题解 设$Li$表示第$ ...

最新文章

  1. 字符串-拆分和拼接字符串
  2. Linux系统运维成长记
  3. java abs前缀变量_JAVA工具例大全--cn.hutool.setting.AbsSetting读取配置文件例子
  4. Go实现Raft第四篇:持久化和调优
  5. JTS(Geometry)工具类
  6. [转]ubuntu系统瘦身-清理系统垃圾文件
  7. Mac系统升级node
  8. 学用 ASP.Net 之 System.Collections.Specialized.StringDictionary 类
  9. linux acpidtd 进程,clover引导卡在该图上了,求资助
  10. JavaWeb在线商城系统(java+jsp+servlet+MySQL+jdbc+css+js+jQuery)
  11. linux netperf,Netperf性能测试工具
  12. MDM主数据管理平台开发精要
  13. 【编译原理】理解BNF
  14. 网聚云联受邀出席5G和边缘计算高峰论坛,与清华研究院达成战略合作
  15. 程序猿、公关狗、设计狮……知道你们年底苦,该去京东生鲜补补了
  16. 车载信息系统平台的未来发展
  17. c语言程序设计 学籍,c语言学籍信息管理系统设计
  18. 显示器扩展后左右如何设置?
  19. Git入门基础-Chivalrous-专题视频课程
  20. iPad最值得期待的切实改进构想

热门文章

  1. CSS3实现8种Loading效果【第二波】
  2. 反应堆模式最牛的那篇论文--由solidmango执笔翻译
  3. ZH奶酪:自然语言处理工具LTP语言云调用方法
  4. .NET Remoting 入门实例
  5. [转]javascript 判断某页面上的表单数据是否改变过
  6. AndroidStudio安卓原生开发_Activity的IntentFlag的SINGLE_TOP_CLEAR_TOP_REORDER_TO_FRONT的用法---Android原生开发工作笔记90
  7. 快速开发框架工作笔记002---项目开发中整理_整合好的_Netty高并发处理快速开发框架_Netty快速开发框架
  8. 持续集成部署Jenkins工作笔记0014---curl命令触发构建
  9. ASP.NET工作笔记014---用VB.NET封装服务器端控件
  10. senet-运行和结构篇