![](https://pic002.cnblogs.com/images/2012/304165/2012081221462545.png)
如图所示,当k==3时,如果我们扫描到红线所在的位置。
则符合条件的区间就是从红线到两条紫线所包含的区间(左开右闭,图上表现的不好,注意)
所以我们可以在“数轴”上进行标记,从而对于query进行正确的回答。
当然,我们先要把树转换成数组才行。
#include #include #include #include #include #include #include #include
pl[SIZE];vector
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
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 =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