poj 2352 Stars (树状数组||线段树)

poj 2352题目链接

题意:给出n个星星的位置,一个星星的level定义为其左下角(不严格)星星的数量。

要求统计0到n-1 level的星星各有多少个。

下面是一年前写的树状数组的题解:

依然想不通,智商是硬伤,绝望的想哭,真的想哭。

更新于2015年08月04日01:47:18:

好像有点明白了.....详情看注释

树状数组ac代码:

/*************************************************************************
	> File Name: code/poj/2352.cpp
	> Author: 111qqz
	> Email: rkz2013@126.com 
	> Created Time: 2015年08月04日 星期二 00时33分52秒
 ************************************************************************/

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
#define y0 abc111qqz
#define y1 hust111qqz
#define yn hez111qqz
#define j1 cute111qqz
#define tm crazy111qqz
#define lr dying111qqz
using namespace std;
#define REP(i, n) for (int i=0;i<int(n);++i)  
typedef long long LL;
typedef unsigned long long ULL;
const int inf = 0x7fffffff;
const int N=4E4+7;
int a[N];
int t[N];
int x,y;
int n;
int lowbit (int x)
{
    return x&(-x);
}
void update(int x,int c)
{
    int i;
    for ( int i = x ; i <= 32001 ; i = i + lowbit(i))
    {
	t[i] = t[i] + c;
    }
}
int sum( int x)
{
    int i;
    int res = 0;
    for ( int i = x ; i >= 1 ; i = i-lowbit(i))
    {
	res = res + t[i];
    }
  //  cout<<"x:"<<x<<" res:"<<res<<endl;
    return res;
}
int main()
{
    scanf("%d",&n);
    for ( int i = 0 ; i < n ; i ++ )
    {
	scanf("%d %d",&x,&y);
	a[sum(++x)]++;  // ++x是因为坐标是从0 开始,而树状数组的下标一定是从1开始,不然会TLE
			// sum(++x)是求 ++x 的level
			//
			//
	update(x,1);   //向上更新,对于每一个比x大的位置,由于x的存在,那些位置的点的level都会增加1
	               //比如对于星3,因为星1的读入,我向上更新了星2,星3,星4,星5,这时候他们的level都是1
		       //之后读入星2,更新了星3和星5,星3的level是2,星5的level也是2,之后由于星4,星5的level又加1,为5.
    }
    for ( int i = 0 ; i < n ; i ++ )
    {
	printf("%d\n",a[i]); //数组a存的是level 为i的点有多少个,即为题目所求。
    }
	return 0;
}

当然用线段树也是可以的。 思路同poj 2481 poj 2481 解题报告

/* ***********************************************
Author :111qqz
Created Time :2016年09月04日 星期日 14时31分12秒
File Name :code/poj/r2352.cpp
 ************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define fst first
#define sec second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ms(a,x) memset(a,x,sizeof(a))
typedef long long LL;
#define pi pair < int ,int >
#define MP make_pair
using namespace std;
const double eps = 1E-8;
const int dx4[4]={1,0,0,-1};
const int dy4[4]={0,-1,1,0};
const int inf = 0x3f3f3f3f;
const int N=32005;
int tree[N<<2];//tree的N写成了区间个数的15000,wa了一发。
int ans[N];
int n;
pi a[N];
void PushUp( int rt)
{
    tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}
void update(int p,int l,int r,int rt)
{
    if (l==r)
    {
	tree[rt]++;
	return;
    }
    int m = (l+r)>>1;
    if (p<=m) update(p,lson);
    else update(p,rson);
    PushUp(rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if (L<=l&&r<=R) return tree[rt];
    int m = (l+r)>>1;
    int ret = 0 ;
    if (L<=m)
    {
	int res  =query(L,R,lson);
	ret = ret + res;
    }
    if (R>=m+1)
    {
	int res  = query(L,R,rson);
	ret = ret + res;
    }
    return ret;
}
int main()
{
#ifndef  ONLINE_JUDGE 
    freopen("code/in.txt","r",stdin);
#endif
    scanf("%d",&n);
    ms(ans,0);
    for ( int i = 1 ;i  <= n ; i++) scanf("%d%d",&a[i].fst,&a[i].sec),a[i].fst++,a[i].sec++;
    for ( int i = 1 ; i <= n ; i++)
    {
	int tmp = query(1,a[i].fst,1,32001,1);
	ans[tmp]++;
	update(a[i].fst,1,32001,1);
    }
    for ( int i = 0 ; i <= n-1 ; i++)
	printf("%d\n",ans[i]);
#ifndef ONLINE_JUDGE  
    fclose(stdin);
#endif
    return 0;
}