POJ 2481 Cows && POJ 2352 Stars(树状数组妙用)

题目链接:POJ 2481 Cows

POJ 2352 Stars

发现这两个题目都跟求逆序数有着异曲同工之妙,通过向树状数组中插入点的位置,赋值为1,或者++,然后通过求和来判断比当前 点 ”“ 的有多少点。

Cows需要自己排序, Stars题目已经给排好序。

POJ 2352 Stars

题目大意为在二维坐标上给出一些星星的坐标,求某一个星星左方,下方,左下方的星星个数。题目已经把星星按照Y坐标从小到大,X从小到大排序。因此,在每次对一个星星进行统计时,之前出现过的星星,只要X坐标比其小,则必在其左,下,左下方。

树状数组储存X的坐标。 就像 求逆序数的方法一样, 统计有多少之前的星星的X坐标小于当前的X坐标。

需要注意的是 X 坐标的范围是32000 ,所以树状数组要开到32000 而不是节点数15000。

【源代码】

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 32010;
int s[maxn];
int level[maxn];
	int n;
int lowbit(int x){
	return x&(-x);
}
int sum(int x){
	int ans = 0;
	for(int i=x;i>0;i-=lowbit(i)){
		ans+=s[i];
	}
	return ans;
}
void add(int x){
	for(int i=x;i<=maxn;i+=lowbit(i)){
		s[i]++;
	}
}
int main(){
	while(scanf("%d",&n)!=EOF){
		int a,b;
		memset(s,0,sizeof(s));
		memset(level,0,sizeof(level)); //初始化
		for(int i=1;i<=n;i++){
			scanf("%d%d",&a,&b);
			++a; //希望节点从1开始而不是0 ,所以++
			level[sum(a)]++; //直接将统计的数量当做level的下标
			add(a); //添加节点
		}
		for(int i=0;i<n;i++){
			printf("%d\n",level[i]);
		}
	}
	return 0;
}

POJ 2481 Cows

和上一题类似的思想,不过需要手动排序。具体怎么做只要上一题弄懂了应该很容易写出来。

坑点在于可能出现相同的区间,在统计的时候简单处理一下就好。

【源代码】

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
const int maxn = 100100;
struct node{
	int st,end;int id;
}cow[maxn];
int s[maxn];
int level[maxn];
int lowbit(int x){ return x&(-x);}
void add(int x){
	for(int i=x;i<=maxn;i+=lowbit(i))
		s[i]++;
}
int sum(int x){
	int ans=0;
	for(int i=x;i>0;i-=lowbit(i)){
		ans+=s[i];
	}
	return ans;
}
bool cmp(const node&a, const node&b){
	if(a.end==b.end)
		return a.st<b.st;
	return a.end>b.end;
}
int main(){
	while(scanf("%d",&n)!=EOF&&n){
		memset(s,0,sizeof(s));
		for(int i=1;i<=n;i++){
			scanf("%d%d",&cow[i].st,&cow[i].end);
			cow[i].st++; //希望节点从1开始 而不是0 ,所以++
			cow[i].id=i;
		}
		sort(cow+1,cow+n+1,cmp);
		for(int i=1;i<=n;i++){
			if(i>1&&cow[i].st==cow[i-1].st&&cow[i].end==cow[i-1].end){ //判重
				level[cow[i].id]=level[cow[i-1].id];
			}
			else
				level[cow[i].id]=sum(cow[i].st);
			add(cow[i].st);
		}
		for(int i=1;i<=n;i++)
		{
			if(i!=1)
				printf(" ");
			printf("%d",level[i]);
		}
		puts("");
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-02 22:54:22

POJ 2481 Cows && POJ 2352 Stars(树状数组妙用)的相关文章

POJ 2352 Stars(树状数组 or 线段树)

链接: http://poj.org/problem?id=2352 题目大意: 在坐标上有n个星星,如果某个星星坐标为(x, y), 它的左下位置为:(x0,y0),x0<=x 且y0<=y.如果左下位置有a个星星,就表示这个星星属于level x 按照y递增,如果y相同则x递增的顺序给出n个星星,求出所有level水平的数量. 思路: 由于输入的顺序,对于第i颗星星,它的等级是之前输入的星星中,横坐标x小于等于i星横坐标的那些星星的总数量(前面的y一定比后面的y小). 所以是查询+更新操作

POJ 2155 Matrix 【二维树状数组】

题目链接:http://poj.org/problem?id=2155 题目大意:给出一个N*N的0矩阵,下面给出两种指令:1. 给出的第一个数据为'C',再给出四个整形数据,x1,y1,y1,y2,对以(x1,y1)(x2,y2)分别为左上角和右下角坐标的矩阵内的元素进行反转(0变1,1变0)         2. 给出的第一个数据为'Q',再给出两个数据,x,y,然后输出此时这个坐标上的元素. 这题用二维树状数组解,树状数组能够对某区间更新所有元素的和,树状数组维护的是c[1][1]到c[i

POJ 2352 &amp;&amp; HDU 1541 Stars (树状数组)

一开始想,总感觉是DP,可是最后什么都没想到.还暴力的交了一发. 然后开始写线段树,结果超时.感觉自己线段树的写法有问题.改天再写.先把树状数组的写法贴出来吧. ~~~~~~~~~~~~~~~~~~~~~~~~ 树状数组不懂的去看刘汝佳的大白书,那个图画得很清楚. 题目大意:星星的坐标以y递增的顺序给出,这些点的左下方的点数代表这个点的级数,问0~N-1的级数有多少个?其实y根本木有用. 题目链接:http://poj.org/problem?id=2352 http://acm.hdu.edu

POJ 2352 &amp;amp;&amp;amp; HDU 1541 Stars (树状数组)

一開始想,总感觉是DP,但是最后什么都没想到.还暴力的交了一发. 然后開始写线段树,结果超时.感觉自己线段树的写法有问题.改天再写.先把树状数组的写法贴出来吧. ~~~~~~~~~~~~~~~~~~~~~~~~ 树状数组不懂的去看刘汝佳的大白书,那个图画得非常清楚. 题目大意:星星的坐标以y递增的顺序给出,这些点的左下方的点数代表这个点的级数,问0~N-1的级数有多少个?事实上y根本木实用. 题目链接:http://poj.org/problem?id=2352 http://acm.hdu.e

POJ 2352 【树状数组】

题意: 给了很多星星的坐标,星星的特征值是不比他自己本身高而且不在它右边的星星数. 给定的输入数据是按照y升序排序的,y相同的情况下按照x排列,x和y都是介于0和32000之间的整数.每个坐标最多有一个星星. 思路: 这题给的输入数据很祥和,间接提示思路了. 用x作为树状数组的区间,然后按照输入的顺序不断查找在包括自己的位置以及左边的星星数. 细节是x可能是0,这是树状数组不能接受的,需要对输入的x数据进行加一操作. 从这题可以看出树状数组最直白的作用就是求从1开始到某个点的某个区间的数量. #

【poj 2892】Tunnel Warfare 二分+树状数组

Tunnel Warfare Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 7576 Accepted: 3127 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaki

POJ 2155 Matrix【二维树状数组+YY(区间更新,单点查询)】

题目链接:http://poj.org/problem?id=2155 Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 32950   Accepted: 11943 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th col

POJ - 2299 - Ultra-QuickSort = 归并排序 + 逆序对 / 树状数组

http://poj.org/problem?id=2299 求逆序对最简单的绝对不会是树状数组,一定是归并排序(认真),不过树状数组会不会快一点呢?理论上应该是树状数组快一点(假如不进行离散化). #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<map> #include<set

POJ 2155 Matrix(二维树状数组)

题意:有一个矩阵,每次操作可以是编辑某个矩形区域,这个区域的0改为1,1改为0,每次查询只查询某一个点的值是0还是1.  思路:这道题和一般的树状数组有一点不同,这道题是区间修改,单点查询,而树状数组处理的是单点修改,所以我们可以改一下矩阵里的每一个值代表的意义.可以注意到我们只关注一个点被翻转了奇数次还是偶数次,令矩阵的元素a[i][j]表示矩形区域(1,1)到(i,j)的修改次数,这样我们可以把区间修改转化为四个端点的单点修改,即modify(x2, y2, 1); modify(x1-