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

如图所示,当k==3时,如果我们扫描到红线所在的位置。

则符合条件的区间就是从红线到两条紫线所包含的区间(左开右闭,图上表现的不好,注意)

所以我们可以在“数轴”上进行标记,从而对于query进行正确的回答。

当然,我们先要把树转换成数组才行。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <deque>
#include <map>//HDU开栈外挂
#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;#define print(x) cout<<x<<endl
#define input(x) cin>>x
#define SIZE 100100struct BIT
{int baum[SIZE];void init(){memset(baum,0,sizeof(baum));}inline int lowbit(int x){return x&(-x);}void add(int x,int val){while(x<SIZE){baum[x]+=val;x+=lowbit(x);}}int sum(int x){int res=0;while(x>0){res+=baum[x];x-=lowbit(x);}return res;}int sum(int l,int r){return sum(r)-sum(l-1);}
};struct query
{int l,r,id;query(){}query(int il,int ir,int iid){l=il;r=ir;id=iid;}friend bool operator < (const query& a,const query& b){return a.r<b.r;}
};int n,k,q;
int w[SIZE];
vector<int> pl[SIZE];
vector<int> g[SIZE];
int lson[SIZE],rson[SIZE],val[SIZE];
int cnt,ind;//重要:将树转化为线性数组
void dfs(int now,int father)
{lson[now]=rson[now]=++ind;val[now]=w[now];for(int i=0;i<(int)g[now].size();i++){int next=g[now][i];if(next!=father){dfs(next,now);rson[now]=rson[next];}}
}int main()
{freopen("input.txt","r",stdin);freopen("out.txt","w",stdout);int T,a,b;BIT bit;query ask[SIZE];int ans[SIZE];map<int,int> mp;input(T);int cas=1;while(T--){bit.init();//树状数组初始化cnt=ind=0;mp.clear();memset(ans,0,sizeof(ans));for(int i=0;i<SIZE;i++) g[i].clear();scanf("%d%d",&n,&k);for(int i=1;i<=n;i++){scanf("%d",&w[i]);if(!mp[w[i]]){mp[w[i]]=++cnt;pl[cnt].clear();}w[i]=mp[w[i]];//离散化,权值的具体值在本题并没有意义//所以只需要区分开}for(int i=1;i<n;i++){//建树scanf("%d%d",&a,&b);g[a].push_back(b);g[b].push_back(a);}//使用DFS对树进行重编号,将树转化为线性数组//使任一非叶子节点的lson,rson值为一个连续区间dfs(1,-1);scanf("%d",&q);for(int i=0;i<q;i++){scanf("%d",&a);ask[i]=query(lson[a],rson[a],i);//离线处理,对query排序}sort(ask,ask+q);int ptr=0;for(int i=1;i<=n;i++){//val[i]代表对于重编号后的i点代表的权值int v=val[i];pl[v].push_back(i);int sz=pl[v].size();//已经遍历了多少个v值if(sz>=k)//如果已经遍历了多于/等于k个v{if(sz==k){//特殊情况,特判bit.add(pl[v][sz-k],1);//对于满足条件的右区间进行+1操作}if(sz>k){//我们现在只考虑一个v值的情况//若区间[a+1...i][a+2...i]...[b...i]符合sum(v,[x...i])==k的条件//则从i点向左查找,如果包含b,不包含a,说明有k个v点.//如果不包含a,b,则说明有不到k个点,不计入答案//如果同时包含a,b,则说明超过k个点,也不计入答案//于是将点(a)标记为-1,将点(b)标记为1,//所以对于一个区间[x...i],如果sum([x...i])==1,则说明有k个v值//将此推广到多个v值同样成立bit.add(pl[v][sz-k-1],-2);//-1是将上一次的增加恢复原状,再-1是维护下一次的状态bit.add(pl[v][sz-k],1);}}while(ask[ptr].r==i){int id=ask[ptr].id;//使用数状数组求区间和ans[id]=bit.sum(ask[ptr].l,ask[ptr].r);ptr++;}}printf("Case #%d:\n",cas++);for(int i=0;i<q;i++){printf("%d\n",ans[i]);}if(T) puts("");}return 0;
}

  

转载于:https://www.cnblogs.com/Wizmann/archive/2012/08/12/2635481.html

HDU 4358 树状数组+思路相关推荐

  1. HDU 4638 Group 树状数组 + 思路

    实际上就是问这个区间编号连续的段的个数,假如一个编号连续的段有(a+b)个人,我把他们分在同一组能得到的分值为(a+b)^2,而把他们分成人数为a和b的两组的话,得到的分值就是a^2+b^2,显然(a ...

  2. hdu 4991(树状数组优化dp)

    Ordered Subsequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  3. hdu 3333 树状数组+离线处理

    思路:既然要求的是不同的元素的和,那么我们可以想办法让每个值在区间中只出现一次,于是想到了离线的算法:将查询按照右端点排序,位置在右端点之前的元素都插入到树状数组中,对于已经出现过的值,我们要先删除( ...

  4. hdu 4417(树状数组+离线算法)

    解题思路:这道题要求某区间内比h小的个数,其实这里可以类似于树状数组求逆序数那样.关键是如何转换成树状数组的模型,这才是本题的难点. 我们首先分析,如果知道h在该区间的哪个位置,那么剩下的就很好做了. ...

  5. hdu 1394(树状数组求逆序数)

    解题思路:这道题是求循环数组中逆序数最小值,求逆序数这里肯定是用树状数组.只是这里有一点点变化,由于题目中n位数是0-n-1的一个排列,所以num[i]可表示为比num[i]小的数的个数.把第一位的数 ...

  6. hdu 1166 树状数组解

    树状数组解决   (关于树状数组参考大佬的博客https://www.cnblogs.com/hsd-/p/6139376.html) 然后就很好理解这题了,代码附上 /*hdu 1166 单点修改, ...

  7. HDU - 5775 树状数组

    题意: 给出一个排列,要求用题目中的排序算法排序之后,算出每个数所到达的最左端和最右端位置的绝对值之差. 思路: 树状数组,每个数往右移动的距离就是右边比它小的数的个数,而左端点的位置就是初始位置和最 ...

  8. hdu 5465 (树状数组 + 博弈)

    题意:基于矩阵的NIM游戏,求异或和. 思路:在x1,y1 到 x2, y2的异或和 =  A[ x2 ][ y2 ] ^ A[x1-1][ y2 ] ^ A[ x2 ][y1 - 1] ^ A[ x ...

  9. Weak Pair HDU - 5877 树状数组+离散化+DFS遍历

    题意 给我们一颗有根有向树 以及每个点得权值a[1]~a[n] 需要我们求出在这颗树种有多少对满足以下两个条件的pair (1)u是v的祖先节点 (2)a[u]*a[v]<= k N<=1 ...

最新文章

  1. Rose VS PowerDesigner
  2. hive中的绣花模型_hive建模方法
  3. sizebox模型下载_css 盒模型、box-sizing 学习笔记
  4. Git命令家底儿及Git数据通信原理详解
  5. [BZOJ3206][Apio2013]道路费用
  6. uva140 Bandwidth
  7. shell 死循环if判断_Shell的条件判断
  8. linux内存真实使用情况,为什么TOP看不出真实的内存占用情况?
  9. [转]使用debugger调试JavaScript脚本
  10. Android视频开发基础(二)
  11. [转载] Netty
  12. 连锁药店计算机系统权限审批表,GSP认证药店管理系统
  13. plsqldev1105_x64与instantclient_11_2配置使用
  14. 六步换向两两导通和三三导通的区别2
  15. 数字信号处理基础----正交基与正交函数集
  16. linux dot命令,linux绘图工具之dot
  17. java爬取当当网所有分类的图书信息(ISBN,作者,出版社,价格,所属分类等)
  18. uni-app开发 常见异常和解决办法
  19. 为什么说每个软件工程师,都该懂大数据技术?
  20. php 对象教程,创建一个简单的PHP对象_PHP教程

热门文章

  1. h.264的NAL和VCL
  2. python监控数据库_【Python】NavicatPre查询日志监控并转存数据库
  3. date比较大小 mybatis_MyBatis版本升级导致OffsetDateTime入参解析异常问题复盘
  4. c++程序影像读取_应急响应手册程序执行痕迹
  5. java SAX 防xml注入,如何防止XML注入像XML Bomb和XXE攻击
  6. 服务器维护日常需做哪些工作?
  7. 计算机php外文翻译,php外文翻译.doc
  8. oracle Router,Oracle官方轻量级中间件MySQL Router介绍与性能测试
  9. HDU1874(SPFA算法)
  10. 习题5-5 使用函数统计指定数字的个数 (15 分)