Problem 2245 动态树

Accept: 17    Submit: 82
Time Limit: 3000 mSec    Memory Limit : 65536 KB

 Problem Description

YellowStar拥有一棵神奇的动态树,该树由n个带权结点,n-1条边构成,任意两个结点互相可达,标号为i结点的权值为Wi。

由于物质是运动的,这棵树每天都会发生一些变化,在第i天,该树权值在[l,r]的结点会发出强烈的光芒,YellowStar看到这一现象会非常的愉悦,它的愉悦值取决于:发光的这些结点构成了多少个连通子树。

现在你知道动态树在接下来m天的发光情况,请你计算出YellowStar每一天的愉悦值

 Input

第一行输入T,表示有T组样例(T <= 20)

每组样例第一行为n,表示树的结点个数(1 <= n <= 1e5)

接下来n个数字W1, W2, ... , Wn (1 <= Wi <= 1e9)表示每个结点的权值

接下来n - 1行,每一行两个数字u, v (1 <= u, v <= n)表示树边

接下来一个数字m(1 <= m <= 1e5),表示m天

接下来m个询问,每个询问一行l, r (1 <= l <= r <= 1e9)表示每一天发光的结点的权值区间

 Output

每组样例输出m行,表示YellowStar在这m天的愉悦值

 Sample Input

1
3
1 3 2
1 2
1 3
3
1 3
1 2
2 3

 Sample Output

1
1
2

 Hint

long long类型请用%I64d输出

 Source

FOJ有奖月赛-2017年4月(校赛热身赛)

【分析】给你一棵树,每个节点有一个权值([1,1e9]),然后Q次询问,每次给出一个区间[l,r],问权值处在这个区间内的节点构成的联通块有多少个。
 一开始想到的是并查集+莫队,后来发现并查集那边不好处理。听了学长的,先将所有权值离散,区间离线,按照右端点从小到大排序。然后对于,每一条边,也看成一个区间
跟前面一样排序。然后,对于一次查询区间,这个区间里有多少点这个我们是可以预处理出来的,假设是S个,也就是没有边的时候联通块是S个,若其中有两个点连有一条边,
那么联通块-1,有多少边,S就减多少。现在的问题转化成了查询区间内有多少边。由于我们是排了序的,所以我们固定查询的右端点,对于右端点<=查询右端点的边,用树状数组
统计<=右端点的边有多少就行了。
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <map>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int>pii;
const int N = 1e5+;
const double eps = 1e-;
int T,n,w[N],sum[N<<],p[N<<],cnt,m,ret[N],c[N<<];
struct Query{
int l,r,id;
bool operator<(const Query &rhs)const{
return r<rhs.r;
}
}q[N],t[N];
void add(int x){
for(;x<=cnt;x+=x&-x)++c[x];
}
int ask(int x){
int ret = ;
for(;x>;x-=x&-x)ret+=c[x];
return ret;
}
int main() {
scanf("%d",&T);
while(T--){
scanf("%d",&n);
cnt = ;
for(int i=;i<=n;++i){
scanf("%d",&w[i]);
p[++cnt]=w[i];
}
for(int i=;i<n;++i){
scanf("%d%d",&t[i].l,&t[i].r);
t[i].l=w[t[i].l];
t[i].r=w[t[i].r];
}
scanf("%d",&m);
for(int i=;i<=m;++i){
scanf("%d%d",&q[i].l,&q[i].r);
p[++cnt]=q[i].l;
p[++cnt]=q[i].r;
q[i].id=i;
}
sort(p+,p++cnt);
cnt=unique(p+,p++cnt)-p-;
for(int i=;i<=cnt;++i)c[i]=sum[i]=;
for(int i=;i<=n;++i){
w[i]=lower_bound(p+,p++cnt,w[i])-p;
++sum[w[i]];
}
for(int i=;i<=cnt;++i)sum[i]+=sum[i-];
for(int i=;i<n;++i){
t[i].l=lower_bound(p+,p++cnt,t[i].l)-p;
t[i].r=lower_bound(p+,p++cnt,t[i].r)-p;
if(t[i].l>t[i].r)swap(t[i].l,t[i].r);
}
for(int i=;i<=m;++i){
q[i].l=lower_bound(p+,p++cnt,q[i].l)-p;
q[i].r=lower_bound(p+,p++cnt,q[i].r)-p;
}
if(n!=)sort(t+,t++n-);
sort(q+,q++m);
int j=;
for(int i=;i<=m;++i){
ret[q[i].id]=sum[q[i].r]-sum[q[i].l-];
for(;j<=n-&&t[j].r<=q[i].r;++j)add(t[j].l);
ret[q[i].id]-=ask(q[i].r)-ask(q[i].l-);
}
for(int i=;i<=m;++i)printf("%d\n",ret[i]);
}
return ;
}
 

最新文章

  1. SGU 319. Kalevich Strikes Back (线段树)
  2. [C#] 编程控制笔记本蓝牙与外部蓝牙设备通信
  3. CocoaPods 安装的第三方删除
  4. 将HTMLCollection/NodeList/伪数组转换成数组
  5. *ecshop安装模板
  6. ffmpeg+rtsp+dss
  7. coherence初识
  8. java泛型小总结
  9. LeetCode_Populating Next Right Pointers in Each Node II
  10. 关于DLL的学习
  11. Jetson TX2刷机教程(原创)
  12. 浅谈cookie和session
  13. Postman 安装及使用入门教程(我主要使用接口测试)
  14. rem布局原理深度理解(以及em/vw/vh)
  15. 2018-2019 前期任务(一):资料阅读&amp;Python入门
  16. Angular使用总结 --- 搜索场景中使用rxjs的操作符
  17. c语言连接mysql数据库的实现方法
  18. 【BZOJ3489】A simple rmq problem(KD-Tree)
  19. lucene删除索引——(五)
  20. 前端-CSS-9-文本和字体-背景颜色

热门文章

  1. PowerDesigner16 时序图
  2. Docker explainations
  3. PACM Team(牛客第三场多校赛+dp+卡内存+打印路径)
  4. 转一篇sublime必备的一些插件
  5. bzoj 3207 可持久化线段树
  6. vue双向绑定原理源码解析
  7. kolakoski序列
  8. windows+nexus+maven环境搭建(转)
  9. Django【进阶】数据库查询性能相关
  10. 【bzoj3682】Phorni