hdu1556树状数组

来源:互联网 发布:淘宝上卖的红酒真吗 编辑:程序博客网 时间:2024/06/08 02:19
 

 

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

 

染色,每次染[a, b],然后查询所有1--n个节点每个节点被染得次数。。。

以前做过类似的,但是没有理解梳妆数组反向用的奥妙。。。其实就是将常规的查询和更新操作反向了。。。

对更新[a, b],则将a位置加1就相当于将这个位置往后的地方全部加1了,然后将b+1位置减1就相当于将这个位置往后的位置都减1了,那下次查找的位置x如果在这个区间后面的话,肯定就没有被加1了,如果x在a与b的中间,则一定加1了。。。

 

后来无语大牛说其实可以不用树状数组。。。先对查询排序,然后按照上面的思想加1减1就可以了。。。因为这题没有中途查询的情况。。。

 

其二维情况pku2155,同样的。。。

 

 

代码;

 

#include <stdlib.h>#include <conio.h>#include <malloc.h>#include <time.h>#include <string.h>#include <stdio.h>#include <memory.h>#include <vector>#include <string>#include <stack>#include <queue>#include <fstream>#include <cmath>#include <iomanip>#include <time.h>#include <stdio.h>#include <algorithm>#include <cmath>#include <iostream>using namespace std;const int N=100010;int n, m, ans;int a[N], sum[N];vector<int> xx[N], yy[N];int query(int i){int tmp = 0;for(; i>0; i-=i&(-i))tmp += sum[i];return tmp;}void update(int i, int v){for(; i<=n; i+=i&(-i))sum[i] += v;}int main(){int i, j, k, x, y, cas;while(scanf("%d", &n)!=EOF){if(n==0)break;for(i=1; i<=n; i++){sum[i] = 0;}for(i=1; i<=n; i++){scanf("%d%d", &x, &y);update(x, 1);update(y+1, -1);}for(i=1; i<n; i++)printf("%d ", query(i));printf("%d\n", query(i));}return 0;}

原创粉丝点击