树状数组(4)

1、Sgu 180 Inversions

 http://acm.sgu.ru/problem.php?contest=0&problem=180

代码忘了放哪了,离散化,求逆序数。。。。习惯很重要啊。

2、POJ 2155 Matrix

 http://acm.pku.edu.cn/JudgeOnline/problem?id=2155

二维的成段更新,单点查询。理解了一维,二维画图也就理解了。记录更新次数,mod 2即求出为0或为1。

#include <stdio.h>
#include <string.h>
const int MAX = 1000+10;
int n;
int c[MAX][MAX];

int lowbit(int x)
{
	return x&(-x);
}

void update(int x, int y, int v)
{
	int i, j;
	for (i=x; i<=n; i+=lowbit(i))
	{
		for (j=y; j<=n; j+=lowbit(j))
		{
			c[i][j] += v;
		}
	}
}

int getsum(int x, int y)
{
	int i, j, sum = 0;
	for (i=x; i>0; i-=lowbit(i))
	{
		for (j=y; j>0; j-=lowbit(j))
		{
			sum += c[i][j];
		}
	}
	return sum;
}
int main()
{
	
	int t, x1, y1, x2, y2, T, tmp;
	char ins;
	scanf("%d", &t);
	{
		tmp = 0;
		while (t--)
		{
			if (tmp)
			{
				puts("");
			}
			tmp++;
			memset(c, 0, sizeof(c));
			scanf("%d%d",&n, &T);
			//printf("%d %d\n", n, T);
			while (T--)
			{
				getchar();
				scanf("%c%d%d", &ins, &x1, &y1);
				if (ins == 'C')
				{
					scanf("%d%d", &x2, &y2);
					//printf("%c%d%d%d%d\n\n\n", ins, x1, y1, x2, y2);
					update(x1, y1, 1);
					update(x2+1, y2+1, 1);
					update(x1, y2+1, -1);
					update(x2+1, y1, -1);
				}
				if (ins == 'Q')
				{
					printf("%d\n", getsum(x1, y1)%2);
				}
				//printf("%d\n", T);
			}
		}
	}
	return 0;
}


3、POJ 3321 Apple Tree

 http://acm.pku.edu.cn/JudgeOnline/problem?id=3321

好像最近一次的浙大月赛也是和此题类似。DFS映射根节点管理区间,然后用树状数组解决。(浙大月赛好像用线段树维护)

#include <stdio.h>
#include <string.h>
const int MAX = 100000+10;
int begin[MAX], end[MAX], t, c[MAX];
int n, m;
char q;
int e, head[MAX], next[MAX<<1], pnt[MAX<<1];
bool visit[MAX];
bool apple[MAX];
void addedge(int u, int v)
{
	pnt[e] = v;
	next[e] = head[u];
	head[u] = e++;
}
int lowbit(int x)
{
	return x&(-x);
}

void update(int x, int v)
{
	while (x<=n)
	{
		c[x] += v;
		x+=lowbit(x);
	}
}

int getsum(int x)
{
	int sum = 0;
	while (x)
	{
		sum += c[x];
		x-=lowbit(x);
	}
	return sum;
}
void dfs(int u)
{
	int i, v;
	begin[u] = ++t;
	visit[u] = true;
	for (i=head[u]; i!=-1; i=next[i])
	{
		v = pnt[i];
		if (!visit[v])
		{
			dfs(v);
		}
	}
	end[u] = t;
}
int main()
{
	int u,v, i;
	while (scanf("%d", &n) == 1)
	{
		e = 0;
		t = 0;
		memset(c, 0, sizeof(c));
		memset(head, -1, sizeof(head));
		memset(visit, false, sizeof(visit));
		memset(apple, true, sizeof(apple));
		for (i=1; i<n; i++)
		{
			scanf("%d%d", &u, &v);
			addedge(u, v);
			addedge(v, u);
		}
		dfs(1);
		for (i=1;i<=n; i++)
		{
			update(i, 1);
		}
		scanf("%d", &m);
		while (m--)
		{
			//printf("%d\n", m);
			getchar();
			scanf("%c%d", &q, &u);
			if (q == 'C')
			{
				if (!apple[u])
				{
					apple[u] = true;
					update(begin[u], 1);
				}
				else
				{
					apple[u] = false;
					update(begin[u], -1);
				}
			}
			else
			{
				printf("%d\n", getsum(end[u]) - getsum(begin[u]-1));
			}
		}
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值