Ch’s gift

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2534    Accepted Submission(s): 887

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=6162

Problem Description

Mr.
Cui is working off-campus and he misses his girl friend very much.
After a whole night tossing and turning, he decides to get to his girl
friend's city and of course, with well-chosen gifts. He knows neither
too low the price could a gift be since his girl friend won't like it,
nor too high of it since he might consider not worth to do. So he will
only buy gifts whose price is between [a,b].
There are n cities in
the country and (n-1) bi-directional roads. Each city can be reached
from any other city. In the ith city, there is a specialty of price ci
Cui could buy as a gift. Cui buy at most 1 gift in a city. Cui starts
his trip from city s and his girl friend is in city t. As mentioned
above, Cui is so hurry that he will choose the quickest way to his girl
friend(in other words, he won't pass a city twice) and of course, buy as
many as gifts as possible. Now he wants to know, how much money does he
need to prepare for all the gifts?
 

Input

There are multiple cases.

For each case:
The first line contains tow integers n,m(1≤n,m≤10^5), representing the number of cities and the number of situations.
The second line contains n integers c1,c2,...,cn(1≤ci≤10^9), indicating the price of city i's specialty.
Then n-1 lines follows. Each line has two integers x,y(1≤x,y≤n), meaning there is road between city x and city y.
Next
m line follows. In each line there are four integers
s,t,a,b(1≤s,t≤n;1≤a≤b≤10^9), which indicates start city, end city, lower
bound of the price, upper bound of the price, respectively, as the
exact meaning mentioned in the description above

 

Output

Output m space-separated integers in one line, and the ith number should be the answer to the ith situation.
 

Sample Input

5 3
1 2 1 3 2
1 2
2 4
3 1
2 5
4 5 1 3
1 1 1 1
3 5 2 3

Sample Output

7 1 4
 

Source

 

题意

给你一棵树,每个点有点权,每次求一条路径点权大于等于a小于等于b的点权和,即求vi的和(a<=vi<=b)
 

题解

我在上次南昌网络赛遇到几乎一模一样的题,当时直接树链剖分+主席数过了,结果这次T了,而且这题数据暴力都能过,我还很不服气的拿暴力对拍,结果真的真的比暴力慢了三四倍吧,想哭了。
在这题上耗了两小时,终于选择向大佬低头,去看题解了,果然我还是太弱了。

以上来自以为蒟蒻的内心独白,接下来假装自己想出来的,讲波题解:
 
我们令sum(x)表示小于等于x的权值和,那么ans=sum(b)-sum(a-1)。当然对于每条路径,sum(x)都不一样,真的吗。
对于一条路径(l,r,a,b)先拆成两个路径,即(l,r,a-1,-1)和(l,r,b,1),并统称为(l,r,val,id),分别求答案,最后相减即可。
然后我们问题转化成了求路径小于等于val的权值和。
对两条路径(l1,r1,val1,id1) 和(l2,r2,val2,id2) ,如果val1<val2那么第一条路径的答案被第二条路径的答案包含。
接下来定义get_sum(u,v)为点u到v路径的权值和,一开始每个点都等于零。
这样不难想到将所有路径按val 从小到大排序,然后扫描路径数组,每次将树上节点权值小于等于val的所有点加上该点的权值,此路径的ans=get_sum(l,r)。
 

AC代码

 #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<<];
struct Edge{int from,to,s;}edges[N<<];
struct Tree{int l,r;ll sum;}tr[N<<];
template<typename T>void read(T&x)
{
ll k=; char c=getchar();
x=;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit();
while(isdigit(c))x=x*+c-'',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]+;
size[x]=;
son[x]=;
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]==)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=;
if (l==r)return;
int mid=(l+r)>>;
bt(x<<,l,mid);
bt(x<<|,mid+,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)>>;
if (p<=mid)update(x<<,p,tt);
if (mid<p)update(x<<|,p,tt);
tr[x].sum=tr[x<<].sum+tr[x<<|].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)>>; ll ans=;
if (l<=mid)ans+=query(x<<,l,r);
if (mid<r)ans+=query(x<<|,l,r);
return ans;
}
ll get_sum(int x,int y)
{
int fx=top[x],fy=top[y];ll ans=;
while(fx!=fy)
{
if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
ans+=query(,rk[fx],rk[x]);
x=fa[fx]; fx=top[x];
}
if (dp[x]<dp[y])swap(x,y);
ans+=query(,rk[y],rk[x]);
return ans;
}
void work()
{
read(n); read(m);
for(int i=;i<=n;i++)read(a[i].val),a[i].id=i;
for(int i=;i<=n-;i++)
{
int x,y;
read(x); read(y);
AddEdge(x,y);
AddEdge(y,x);
}
int num=;
for(int i=;i<=m;i++)
{
int l,r,x,y;
read(l); read(r); read(x);read(y);
que[++num]=Query{l,r,-i,x-};
que[++num]=Query{l,r,i,y};
}
sort(a+,a+n+);
sort(que+,que+num+);
dfs1(,);
dfs2(,);
bt(,,n);
int ds=;
for(int i=;i<=num;i++)
{
while(ds<=n&&a[ds].val<=que[i].val)
{
update(,rk[a[ds].id],a[ds].val);
ds++;
}
ll sum=get_sum(que[i].l,que[i].r);
if (que[i].id<) ans[-que[i].id]-=sum;
else ans[que[i].id]+=sum;
}
printf("%lld",ans[]);
for(int i=;i<=m;i++)printf(" %lld",ans[i]);
printf("\n");
}
void clear()
{
tot=; cnt=;
memset(last,,sizeof(last));
memset(ans,,sizeof(ans));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
//freopen("my.out","w",stdout);
#endif
while()
{
clear();
work();
}
}

TLE代码(树链剖分+主席树)

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100050
#define INF 123456789
int n,m,w[N];ll b[N];
int tot,last[N];
int tree_num,root[N];
int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N];
struct Edge{int from,to,s;}edges[N<<];
struct Tree{int l,r,ls,rs;ll sum;}tr[];
template<typename T>void read(T&x)
{
ll k=; char c=getchar();
x=;
while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
if (c==EOF)exit();
while(isdigit(c))x=x*+c-'',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]+;
size[x]=;
son[x]=;
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]==)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)
{
x=++tree_num;
tr[x].l=l; tr[x].r=r; tr[x].sum=;
if (l==r)return;
int mid=(l+r)>>;
bt(tr[x].ls,l,mid);
bt(tr[x].rs,mid+,r);
}
void add(int &x,int last,int p)
{
x=++tree_num;
tr[x]=tr[last];
tr[x].sum+=b[p];
if (tr[x].l==tr[x].r)return;
int mid=(tr[x].l+tr[x].r)>>;
if(p<=mid)add(tr[x].ls,tr[last].ls,p);
else add(tr[x].rs,tr[last].rs,p);
}
ll ask(int x,int y,int p)
{
if (tr[x].r<=p)return tr[y].sum-tr[x].sum;
int mid=(tr[x].l+tr[x].r)>>;ll ans=;
if (<=mid)ans+=ask(tr[x].ls,tr[y].ls,p);
if (mid<p)ans+=ask(tr[x].rs,tr[y].rs,p);
return ans;
}
ll get_sum(int x,int y,int tt)
{
int fx=top[x],fy=top[y];ll ans=;
while(fx!=fy)
{
if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy);
ans+=ask(root[rk[fx]-],root[rk[x]],tt);
x=fa[fx]; fx=top[x];
}
if (dp[x]<dp[y])swap(x,y);
ans+=ask(root[rk[y]-],root[rk[x]],tt);
return ans;
}
void work()
{
read(n); read(m);
int num=;
for(int i=;i<=n;i++)read(w[i]),b[++num]=w[i];
b[++num]=INF;
for(int i=;i<=n-;i++)
{
int x,y;
read(x); read(y);
AddEdge(x,y);
AddEdge(y,x);
}
sort(b+,b+num+);
num=unique(b+,b+num+)-b-;
dfs1(,);
dfs2(,);
bt(root[],,num);
for(int i=;i<=n;i++)
{
int tt=lower_bound(b+,b+num+,w[kth[i]])-b;
add(root[i],root[i-],tt);
}
for(int i=;i<=m;i++)
{
if (i>)printf(" ");
int x,y,l,r;
read(x); read(y); read(l); read(r);
l=lower_bound(b+,b+num+,l)-b-;
r=upper_bound(b+,b+num+,r)-b-;
ll ans=get_sum(x,y,r);
ans-=get_sum(x,y,l);
printf("%lld",ans);
}
printf("\n");
}
void clear()
{
tot=; cnt=; tree_num=;
memset(last,,sizeof(last));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("aa.in","r",stdin);
#endif
while()
{
clear();
work();
}
}

L - Ch’s gift HDU - 6162的更多相关文章

  1. 2017 Multi-University Training Contest - Team 9 1002&&HDU 6162 Ch’s gift【树链部分+线段树】

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  2. HDU 6162 - Ch’s gift | 2017 ZJUT Multi-University Training 9

    /* HDU 6162 - Ch’s gift [ LCA,线段树 ] | 2017 ZJUT Multi-University Training 9 题意: N节点的树,Q组询问 每次询问s,t两节 ...

  3. HDU 6162 Ch’s gift (树剖 + 离线线段树)

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  4. hdu6162 Ch’s gift

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6162 题目: Ch’s gift Time Limit: 6000/3000 MS (Java ...

  5. Ch’s gift

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Proble ...

  6. 2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162 题意:给出一棵树的链接方法,每个点都有一个数字,询问U->V节点经过所有路径中l < ...

  7. 【HDU 6162】 Ch’s gift

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6162 [算法] 离线树剖 我们知道,u到v路径上权值为[A,B]的数的和 = u到v路径上权值小于 ...

  8. HDU 6162 Ch’s gift

    Mr. Cui is working off-campus and he misses his girl friend very much. After a whole night tossing a ...

  9. HDU 6162 Ch's gift(树链剖分+线段树)

    题意: 已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点u到节点v的最短路径上的节点值在l到r之间的节点值的和. 思路: 用树链剖分将树映射到线段树上,线段树上维护3个值,max,mi ...

随机推荐

  1. 装饰器1、无参数的装饰器 2、有参数的装饰器 3、装饰器本身带参数的以及如果函数带return结果的情况

     装饰器分成三种: 1.无参数的: 2.有参数的: 3.装饰器本身带参数的. 装饰器decorator又叫语法糖 定义:本质是函数,器就是函数的意思.装饰其他函数.就是为其他函数添加附加功能. 原则: ...

  2. Unity Shader入门教程(三)自制光照模型

    光照模型的概念目前还不明晰,因为笔者也是一个初学者,所以请小心对待笔者介绍的内容.笔者认为光照模型是规定光照算法的模型,比如说前面提到的Lambert光照模型,规定了材质表面的光线的表达式为 环境光+ ...

  3. springboot成神之——basic auth和JWT验证结合

    本文介绍basic auth和JWT验证结合 目录结构 依赖 config配置文件WebSecurityConfig filter过滤器JWTLoginFilter filter过滤器JWTAuthe ...

  4. STM32用有源蜂鸣器实现闹钟的声响

    有源蜂鸣器的声音是固定的,工作电压恒定,改变通断电的时间获得不同时长的音响,譬如连续音.快速短音.慢速长音(类似莫尔斯电报)来区分不同的报警信息. 简单的说,有源蜂鸣器只能发出一种声音,因为它的频率是 ...

  5. 【开发工具】最强Git使用总结

    目录 必读材料 常用小结 Git操作流程 Git常用操作命令 - 代码提交和同步代码 Git常用操作命令 - 代码撤销和撤销同步 Git常用操作命令 - 其它常用命令 Git是分布式代码托管的标杆,这 ...

  6. 国庆前执行更新承诺SO交期 FP_SO2SAP

    每年9月20日到30号执行以下程序:创建日期为昨天的订单,且承诺交期为10月1到3号,则承诺交期需加7天:创建日期为昨天的订单, 承诺交期为4号到11月1日,承诺交期需加4天 存储过程:FP_SO2S ...

  7. 利用PHPExcel将数据导出到xls格式的excel文件

    在开发某地的经营许可证管理系统的时候需要将数据导出打excel文件,虽然一年前做某集团的ERP的时候用到过一次导入和导出,但是那时候太忙没时间写博客,一年过去了我也忘的差不多了,所以趁着今天将此次的使 ...

  8. SpringBoot25 gradle安装、利用gradle创建SrpingBoot项目

    1 gradle安装 技巧01:gradle依赖JDK或者JRE,而且版本至少时1.7 1.1 下载安装包 到gradle官网下载安装包[PS: 也可以利用命令的方式安装,本案例是利用安装包的方式] ...

  9. 643. Maximum Average Subarray I 最大子数组的平均值

    [抄题]: Given an array consisting of n integers, find the contiguous subarray of given length k that h ...

  10. 283. Move Zeroes把零放在最后面

    [抄题]: Given an array nums, write a function to move all 0's to the end of it while maintaining the r ...