hdu1556树状数组

 

 

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;
}

你可能感兴趣的:(hdu1556树状数组)