研究了整整一天orz……直接上官方题解神思路

 #include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm> using namespace std; const int MAXN = ; struct node
{
int v, next;
}; struct subTree
{
int st, ed;
}; struct Queryy
{
int i;
int st, ed;
}; int N, K, Q;
int EdgeN, TimeFlag;
node D[MAXN]; //树节点
int C[MAXN]; //树状数组
int head[MAXN];
subTree tree[MAXN]; //子树映射成线性序列之后对应的区间
Queryy qry[MAXN]; //查询信息
int weight[MAXN], addr[MAXN];
int ans[MAXN];
vector<int> pos[MAXN]; void AddEdge( int u, int v )
{
D[EdgeN].v = v;
D[EdgeN].next = head[u];
head[u] = EdgeN++;
return;
} void DFS( int cur ) //树形结构转线性结构
{
tree[ cur ].st = ++TimeFlag;
addr[ TimeFlag ] = weight[ cur ];
for ( int i = head[cur]; i != -; i = D[i].next )
DFS( D[i].v );
tree[cur].ed = TimeFlag;
return;
} int lowbit( int x )
{
return (-x) & x;
} void add( int x, int val )
{
while ( x <= N )
{
C[x] += val;
x += lowbit(x);
}
return;
} int query( int x )
{
int res = ;
while ( x > )
{
res += C[x];
x -= lowbit(x);
}
return res;
} bool cmp( int a, int b )
{
return weight[a] < weight[b];
} void init() //将weight离散化
{
sort( addr + , addr + N + , cmp ); int cnt = , pre = -;
for ( int i = ; i <= N; ++i )
{
if ( weight[ addr[i] ] != pre )
pre = weight[ addr[i] ], weight[ addr[i] ] = ++cnt;
else weight[ addr[i] ] = cnt;
}
return;
} bool cmp2( Queryy a, Queryy b )
{
return a.ed < b.ed;
} void solved()
{
for ( int i = ; i <= N; ++i ) pos[i].clear(); sort( qry, qry + Q, cmp2 );
int cur = ;
for ( int i = ; i <= N; ++i )
{
int val = addr[i];
pos[val].push_back(i);
int sz = pos[val].size();
if ( sz == K )
add( pos[val][ sz - K ], );
else if ( sz > K )
{
add( pos[val][ sz - K ], );
add( pos[val][ sz - K - ], - );
}
//printf( "ed = %d\n", qry[cur].ed );
while ( cur < Q && qry[cur].ed == i )
{
int id = qry[cur].i;
ans[id] = query( qry[cur].ed ) - query( qry[cur].st - );
// printf("ans[%d] = %d\n", id, ans[id] );
++cur;
}
}
return;
} int main()
{
int T, cas = ;
scanf( "%d", &T );
while ( T-- )
{
memset( head, -, sizeof( head ) );
memset( C, , sizeof(C) ); scanf( "%d%d", &N, &K );
for ( int i = ; i <= N; ++i )
{
scanf( "%d", &weight[i] );
addr[i] = i;
}
init(); EdgeN = ; for ( int i = ; i < N; ++i ) //建树
{
int u, v;
scanf( "%d%d", &u, &v );
AddEdge( u, v );
} TimeFlag = ;
DFS(); //树形结构转线性结构 scanf( "%d", &Q );
printf( "Case #%d:\n", ++cas );
for ( int i = ; i < Q; ++i )
{
int u;
scanf( "%d", &u );
qry[i].i = i;
qry[i].st = tree[u].st;
qry[i].ed = tree[u].ed;
// printf( "%d %d\n", qry[i].st, qry[i].ed );
}
solved();
for ( int i = ; i < Q; ++i )
printf( "%d\n", ans[i] ); if ( T ) puts("");
}
return ;
}

HDU 4358 Boring counting 树状数组+思路的更多相关文章

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

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

  2. HDU 4325 Flowers(树状数组+离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325 题意:给出n个区间和m个询问,每个询问为一个x,问有多少个区间包含了x. 思路: 因为数据量比较多,所以需 ...

  3. HDU - 1541 Stars 【树状数组】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1541 题意 求每个等级的星星有多少个 当前这个星星的左下角 有多少个 星星 它的等级就是多少 和它同一 ...

  4. HDU 3333 | Codeforces 703D 树状数组、离散化

    HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...

  5. HDU 3854 Glorious Array(树状数组)

    题意:给一些结点,每个结点是黑色或白色,并有一个权值.定义两个结点之间的距离为两个结点之间结点的最小权值当两个结点异色时,否则距离为无穷大.给出两种操作,一种是将某个结点改变颜色,另一个操作是询问当前 ...

  6. hdu 4217 Data Structure? 树状数组求第K小

    Data Structure? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  7. HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)

    题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...

  8. hdu 1541 Stars(树状数组)

    题意:求坐标0到x间的点的个数 思路:树状数组,主要是转化,根据题意的输入顺序,保证了等级的升序,可以直接求出和即当前等级的点的个数,然后在把这个点加入即可. 注意:树状数组下标从1开始(下标为0的话 ...

  9. HDU 3333 Turing Tree (树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3333 题意就是询问区间不同数字的和. 比较经典的树状数组应用. //#pragma comment(l ...

随机推荐

  1. opencv学习笔记(05)——操作相邻区域

    下面的例子以灰度图像为例: #include <opencv2\highgui\highgui.hpp> #include <opencv2\imgproc\imgproc.hpp& ...

  2. Oracle查询出最最近一次的一条记录

    需求:从一个表中查询数据,得到的数据为最新的一条记录. -------------建立测试表 --drop table TB ),dtDate date) -------------插入测试数据 ,' ...

  3. 【Go】 格式处理

    格式化字符串 在golang里面获取时间戳并不难.只要加载time包.time.Now().Unix() fmt.Sprintf("%d",int64),自此,go语言的int转换 ...

  4. jquery定义表格宽度

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. 还原没有日志文件的SQL数据库

    1.执行命令示例: EXEC sys.sp_attach_db @dbname = 'AdventrueWorks2012_Data',     @filename1 = N'C:\Program F ...

  6. Start my cnBlogs

    Compared to CSDN blog, althought it's my first time to use CNBlog,i felt it makes me more comfortabl ...

  7. Asp.net 同时下载多个文件

    整理自网络 下载思路是首先把多个文件进行压缩,然后再下载压缩成的压缩包 引用文件dll:ICSharpCode.SharpZipLib.dll 1. 合成下载文件夹 Protected Sub btn ...

  8. 【HDOJ】【1754】I Hate It

    线段树 这是一道线段树的裸题……带单点修改的RMQ 为什么我会想到写这么一道傻逼题呢?是因为这样……

  9. Matlab中mat2cell的使用

    怎样用mat2cell将一个100*100的矩阵分成10个10*100的矩阵? 根据帮助中 c = mat2cell(x,m,n)应该这样写 mat2cell(x,[10 10 10 10 10 10 ...

  10. eclipse svn 修改了类名之后提交

    win下面的文件名不区分大小写,所以不能只是把小写类名改成大写. 正确的做法有如下两种:1,先删除类a,提交,此操作会删除服务器上的文件.再添加类A,提交.2,重命名a为aa,提交,此操作会删除服务器 ...