Distance on the tree

题目链接

https://nanti.jisuanke.com/t/38229

Describe

DSM(Data Structure Master) once learned about tree when he was preparing for NOIP(National Olympiad in Informatics in Provinces) in Senior High School. So when in Data Structure Class in College, he is always absent-minded about what the teacher says.

The experienced and knowledgeable teacher had known about him even before the first class. However, she didn't wish an informatics genius would destroy himself with idleness. After she knew that he was so interested in ACM(ACM International Collegiate Programming Contest), she finally made a plan to teach him to work hard in class, for knowledge is infinite.

This day, the teacher teaches about trees." A tree with nnn nodes, can be defined as a graph with only one connected component and no cycle. So it has exactly n−1 edges..." DSM is nearly asleep until he is questioned by teacher. " I have known you are called Data Structure Master in Graph Theory, so here is a problem. "" A tree with nnn nodes, which is numbered from 1 to n. Edge between each two adjacent vertexes uuu and v has a value w, you're asked to answer the number of edge whose value is no more than k during the path between u and v."" If you can't solve the problem during the break, we will call you DaShaMao(Foolish Idiot) later on."

The problem seems quite easy for DSM. However, it can hardly be solved in a break. It's such a disgrace if DSM can't solve the problem. So during the break, he telephones you just for help. Can you save him for his dignity?

Input

In the first line there are two integers n,m represent the number of vertexes on the tree and queries(\(2≤n≤10^5,1≤m≤10^5\))

The next n-1 lines, each line contains three integers u,v,w indicates there is an undirected edge between nodes uuu and v with value w. (\(1≤u,v≤n,1≤w≤10^9\))

The next mmm lines, each line contains three integers u,v,k be consistent with the problem given by the teacher above. (\(1≤u,v≤n,0≤k≤10^9\))

Output

For each query, just print a single line contains the number of edges which meet the condition.

样例输入1

3 3

1 3 2

2 3 7

1 3 0

1 2 4

1 2 7

样例输出1

0

1

2

样例输入2

5 2

1 2 1000000000

1 3 1000000000

2 4 1000000000

3 5 1000000000

2 3 1000000000

4 5 1000000000

样例输出2

2

4

题意

给你一棵树,问两个点之间边权小与等于k的数量。

题解

方法一:

比赛时,智商不够,靠数据结构来凑,弱弱的我直接树剖,然后用主席树,感觉就是把两个板子结合一下。第一次一遍AC,看了好几遍才确定自己没看错。

过了n天之后,当我刷完了树链剖分专题,并且遇到了一道和此题相似度极高的题目后,

我终于发现了原来我就是个DaShaMao(Foolish Idiot),完全可以不用主席树。

方法二:

可以看 https://www.cnblogs.com/mmmqqdd/p/10799395.html

这里我也讲一下大概思路:我们先将询问按照val(题目中的k)从小到大排序,那么我们扫一遍询问数组,因为val单增,所以对于每个询问i,我们就把权值小于等于val[i]的位置加一。答案就是直接求u到v的路径和。

方法二很好写,我写了25分钟,一遍AC了。

代码1——树链剖分+主席数(在线,不建议使用)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100050
#define INF 123456789
int n,m;
int tot,last[N];
ll ans[N];
int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
struct Query
{
int l,r,id; ll val;
bool operator <(const Query&b)const
{return val<b.val;}
}a[N],que[N<<1];
struct Edge{int from,to,s;}edges[N<<1];
struct Tree{int l,r;ll sum;}tr[N<<2];
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void AddEdge(int x,int y)
{
edges[++tot]=Edge{x,y,last[x]};
last[x]=tot;
}
void dfs1(int x,int pre)
{
fa[x]=pre;
dp[x]=dp[pre]+1;
size[x]=1;
son[x]=0;
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
dfs1(e.to,x);
size[x]+=size[e.to];
if (size[e.to]>size[son[x]])son[x]=e.to;
}
}
void dfs2(int x,int y)
{
rk[x]=++cnt;
kth[cnt]=x;
top[x]=y;
if (son[x]==0)return;
dfs2(son[x],y);
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==fa[x]||e.to==son[x])continue;
dfs2(e.to,e.to);
}
}
void bt(int x,int l,int r)
{
tr[x].l=l; tr[x].r=r; tr[x].sum=0;
if (l==r)return;
int mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
}
void update(int x,int p,ll tt)
{
if (p<=tr[x].l&&tr[x].r<=p)
{
tr[x].sum+=tt;
return;
}
int mid=(tr[x].l+tr[x].r)>>1;
if (p<=mid)update(x<<1,p,tt);
if (mid<p)update(x<<1|1,p,tt);
tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
}
ll query(int x,int l,int r)
{
if (l<=tr[x].l&&tr[x].r<=r)
return tr[x].sum;
int mid=(tr[x].l+tr[x].r)>>1; ll ans=0;
if (l<=mid)ans+=query(x<<1,l,r);
if (mid<r)ans+=query(x<<1|1,l,r);
return ans;
}
ll get_sum(int x,int y)
{
int fx=top[x],fy=top[y];ll ans=0;
while(fx!=fy)
{
if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
ans+=query(1,rk[fx],rk[x]);
x=fa[fx]; fx=top[x];
}
if (dp[x]<dp[y])swap(x,y);
ans+=query(1,rk[y],rk[x]);
return ans;
}
void work()
{
read(n); read(m);
for(int i=1;i<=n;i++)read(a[i].val),a[i].id=i;
for(int i=1;i<=n-1;i++)
{
int x,y;
read(x); read(y);
AddEdge(x,y);
AddEdge(y,x);
}
int num=0;
for(int i=1;i<=m;i++)
{
int l,r,x,y;
read(l); read(r); read(x);read(y);
que[++num]=Query{l,r,-i,x-1};
que[++num]=Query{l,r,i,y};
}
sort(a+1,a+n+1);
sort(que+1,que+num+1);
dfs1(1,0);
dfs2(1,1);
bt(1,1,n);
int ds=1;
for(int i=1;i<=num;i++)
{
while(ds<=n&&a[ds].val<=que[i].val)
{
update(1,rk[a[ds].id],a[ds].val);
ds++;
}
ll sum=get_sum(que[i].l,que[i].r);
if (que[i].id<0) ans[-que[i].id]-=sum;
else ans[que[i].id]+=sum;
}
printf("%lld",ans[1]);
for(int i=2;i<=m;i++)printf(" %lld",ans[i]);
printf("\n");
}
void clear()
{
tot=0; cnt=0;
memset(last,0,sizeof(last));
memset(ans,0,sizeof(ans));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
while(1)
{
clear();
work();
}
}

代码2--树链剖分+线段树(离线)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100050
int n,m,ans[N];
int tot,last[N];
int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
struct Tree{int l,r,sum;}tr[N<<2];
struct Edge{int from,to,val,s;}edges[N<<1];
struct Query
{
int id,l,r,val;
bool operator <(const Query&b)const
{return val<b.val;}
}que[N],a[N];
template<typename T>void read(T&x)
{
ll k=0; char c=getchar();
x=0;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit(0);
while(isdigit(c))x=x*10+c-'0',c=getchar();
x=k?-x:x;
}
void read_char(char &c)
{while(!isalpha(c=getchar())&&c!=EOF);}
void AddEdge(int x,int y,int z)
{
edges[++tot]=Edge{x,y,z,last[x]};
last[x]=tot;
}
void dfs1(int x,int pre)
{
fa[x]=pre;
dp[x]=dp[pre]+1;
size[x]=1;
son[x]=0;
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==pre)continue;
a[e.to].id=e.to;
a[e.to].val=e.val;
dfs1(e.to,x);
size[x]+=size[e.to];
if (size[e.to]>size[son[x]])son[x]=e.to;
}
}
void dfs2(int x,int y)
{
rk[x]=++cnt;
kth[cnt]=x;
top[x]=y;
if (son[x]==0)return;
dfs2(son[x],y);
for(int i=last[x];i;i=edges[i].s)
{
Edge &e=edges[i];
if (e.to==fa[x]||e.to==son[x])continue;
dfs2(e.to,e.to);
}
}
void bt(int x,int l,int r)
{
tr[x].l=l; tr[x].r=r; tr[x].sum=0;
if (l==r)return;
int mid=(l+r)>>1;
bt(x<<1,l,mid);
bt(x<<1|1,mid+1,r);
}
void update(int x,int p)
{
tr[x].sum++;
if (tr[x].l==tr[x].r)return;
int mid=(tr[x].l+tr[x].r)>>1;
if (p<=mid)update(x<<1,p);
else update(x<<1|1,p);
}
int query(int x,int l,int r)
{
if (l<=tr[x].l&&tr[x].r<=r)return tr[x].sum;
int mid=(tr[x].l+tr[x].r)>>1,a1=0,a2=0;
if(l<=mid)a1=query(x<<1,l,r);
if(mid<r)a2=query(x<<1|1,l,r);
return a1+a2;
}
int get_sum(int x,int y)
{
int fx=top[x],fy=top[y],ans=0;
while(fx!=fy)
{
if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
ans+=query(1,rk[fx],rk[x]);
x=fa[fx]; fx=top[x];
}
if (dp[x]<dp[y])swap(x,y);
ans+=query(1,rk[y]+1,rk[x]);
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
read(n); read(m);
for(int i=1;i<=n-1;i++)
{
int x,y,z;
read(x); read(y); read(z);
AddEdge(x,y,z);
AddEdge(y,x,z);
}
dfs1(1,0);
dfs2(1,1);
bt(1,1,n);
sort(a+1,a+n+1);
for(int i=1;i<=m;i++)
{
que[i].id=i;
read(que[i].l); read(que[i].r); read(que[i].val);
}
sort(que+1,que+m+1);
int top=1;
for(int i=1;i<=m;i++)
{
while(top<=n&&a[top].val<=que[i].val)
{
update(1,rk[a[top].id]);
top++;
}
ans[que[i].id]=get_sum(que[i].l,que[i].r);
}
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
}

最新文章

  1. jsonp 跨域请求
  2. oracle、mysql新增字段,字段存在则不处理
  3. 烂泥:mysql5.5主从同步复制配置
  4. cf#306D. Regular Bridge(图论,构图)
  5. tar 打包文件 除某个文件夹
  6. Android中libs目录下armeabi和armeabi-v7a的区别
  7. 通讯录(ios自带有界面)
  8. spring-mvc xml文件的最基本配置
  9. 英语语法最终珍藏版笔记- 21it 用法小结
  10. ZOJ Monthly, July 2015
  11. Android学习笔记⑦——UI组件的学习AdapterView相关1
  12. Flex xxx-app.xml配置
  13. zoj 3537 Cake 区间DP (好题)
  14. 设置开机启动时指定非ROOT用户执行相应的脚本
  15. MinnowBoard MAX 硬件开发板
  16. Android隐式启动Activity可能存在的坑
  17. Scala的类层级讲解
  18. 数组的常用方法concat,join,slice和splice的区别,map,foreach,reduce
  19. jquery对append进的元素的监听操作
  20. 数据库基础SQL知识面试题二

热门文章

  1. 虚拟机Linux无法查看本地ip地址 解决办法
  2. 全局变量异步I/O
  3. ERRORS: ?: (corsheaders.E013) Origin &#39;*&#39; in CORS_ORIGIN_WHITELIST is missing scheme or netloc HINT:
  4. libpng warning:iCCP:known incorrect sRGB profile
  5. JavaWeb_(Mybatis框架)输入和输出参数_五
  6. java 生成随机数 自定义
  7. Reids入门介绍
  8. 消灭WinRAR广告
  9. centos7远程服务器中redis的安装与java连接
  10. mysql查询表里的重复数据方法