树状数组(1)

 

根据http://blog.csdn.net/w00w12l/article/details/8212782这个博客学习了一些知识,做了一些题目。(第一篇博客,多多指教,看了别人的思路,算不上原创)

1、POJ 2299 Ultra-QuickSort

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

求逆序数,离散化,降序。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 500000+10;
struct node
{
	int num;
	int id;
}a[MAX];
int n, b[MAX], c[MAX];

bool operator<(const node&p1, const node&p2)
{
	return p1.num > p2.num;
}

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

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

int getsum(int x)
{
	int sum = 0;
	while (x)
	{
		sum += c[x];
		x -= lowbit(x);	
	}
	return sum;
}
int main()
{
	int i, j;
	__int64 ans;
	while (scanf("%d",&n) == 1, n)
	{
		ans = 0;
		for (i=1; i<=n; i++)
		{
			scanf("%d", &a[i].num);
			a[i].id = i;
		}
		sort(a+1, a+n+1);
		for (i=1; i<=n; i++)
		{
			b[a[i].id] = i;
		}
		memset(c, 0, sizeof(c));
		for (i=1; i<=n; i++)
		{
			//printf("%d ", a[i].id);
			ans += getsum(b[i]);
			update(b[i], 1);
		}
		printf("%I64d\n", ans);
	}
	return 0;
}

2、POJ 2352 Stars

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

 

#include <cstdio>
#include <cstring>
const int MAX = 32000+10;
int x[MAX/2], y, c[MAX], leave[MAX];

int lowbit(int x)
{
	return x&(-x);
}
void update(int x, int t)
{
	while (x<=MAX)
	{
		c[x] += t;
		x += lowbit(x);
	}	
}
int getsum(int x)
{
	int sum = 0;
	while (x)
	{
		sum += c[x];
		x -= lowbit(x);
	}
	return sum;
	
}
int main()
{
	int n, i;
	while (scanf("%d", &n) == 1)
	{
		memset(c, 0, sizeof(c));
		memset(leave, 0, sizeof(leave));
		for (i=1; i<=n; i++)
		{
			scanf("%d%d", &x[i], &y);
			x[i]++;
			leave[getsum(x[i])]++; 
			update(x[i], 1);
		}
		for (i=0; i<n; i++)
		{
			printf("%d\n", leave[i]);
		}
	}
	return 0;
		
}

 

3、poj2481Cows

http://poj.org/problem?id=2481
大体意思是给一些线段,询问每一个线段包含于多少个线段,先按线段左端降序排列,然后利用树桩数组统计比当前线段右端大的线段数即可。注意线段相等的情况。

#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX  = 100000 + 10;

struct rang
{
	int x;
	int y;
	int id;
}cow[MAX];

int n, ans[MAX], c[MAX];
bool flag[MAX];
bool operator<(const rang& a, const rang& b)
{
	return a.y>b.y ||  a.y == b.y && a.x < b.x;
}

bool operator==(const rang&a, const rang&b) 
{
	return a.x == b.x && a.y == b.y;
}
int lowbit(int x)
{
	return x&(-x);
}

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

int getsum(int x)
{
	int sum = 0;
	while (x)
	{
		sum += c[x];
		x-=lowbit(x);
	}
	return sum;
}
int main()
{
	int i;
	while (scanf("%d", &n) == 1, n)
	{
		memset(c, 0, sizeof(c));
		memset(flag, false, sizeof(flag));
		for (i=1; i<=n; i++)
		{
			scanf("%d%d",&cow[i].x, &cow[i].y);
			cow[i].x++;
			cow[i].y++;
			cow[i].id = i;
		}
		sort(cow+1, cow+n+1);
		for (i=2; i<=n; i++)
		{
			if (cow[i] == cow[i-1])
			{
				flag[i] = true;
			}
		}
		for (i=1; i<=n; i++)
		{
			//ans[cow[i].id] = i-1 - getsum(cow[i].y-1);
			//printf("\n%d %d\n", cow[i].x, cow[i].y);
			if (!flag[i])
			{
				ans[cow[i].id] = getsum(cow[i].x);
			}
			else
			{
				ans[cow[i].id] = ans[cow[i-1].id];
			}
			update(cow[i].x, 1);
		}
		for (i=1; i<n; i++)
		{
			printf("%d ",ans[i]);
		}
		printf("%d\n", ans[i]);
	}
	return 0;

 

4、soj4122

上一题的变形,询问一个点在多少个线段内,涉及到成段更新,单点查询,update函数更新段,getsum函数单点查询。

http://cstest.scu.edu.cn/soj/problem.action?id=4122

/*
ID: lj104302
LANG: C++
TASK: 
*/


/*
next_permutation  prev_permutation
max_element min_element
nth_element
binary_search  upper_bound lower_bound
to_string <char, char_traits <char> , allocator <char> > ()
<cstdlib> atoi, atof, atol, 
sscanf, sprintf
*/


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cstddef>
#include <cctype>
#include <cassert>
#include <map>
#include <set>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <utility>
#include <iomanip>
#include <algorithm>
#define eps 1e-10
#define inf 0x7fffffff
using namespace std;
typedef long long int64;

const int MAX = 100001;
int n, m, beg, end;
struct node
{
    int l;
    int r;
    int cnt;
}no[MAX*8+8];

void bulid(int l, int r, int lev)
{
    no[lev].l = l;
    no[lev].r = r;
    no[lev].cnt = 0;
    if (l == r)
    {
        return;
    }
    int mid = (l+r) / 2;
    bulid(l, mid, lev * 2);
    bulid(mid+1, r, lev*2+1);
}

void insert(int l, int r, int lev)
{
    if (l==no[lev].l && r ==  no[lev].r)
    {
        no[lev].cnt++;
        return;
    }
    int mid = (no[lev].l + no[lev].r) / 2;
    if (r <= mid)
    {
        insert(l, r, lev*2);
    }
    else if (l>mid)
    {
        insert(l, r, lev*2+1);
    }
    else
    {
        insert(l, mid, lev*2);
        insert(mid+1, r, lev*2+1);
    }
}

int query(int val, int pos)
{
    int ans = 0;
    if (val>=no[pos].l && val<=no[pos].r)
    {
        ans += no[pos].cnt;
        //int mid = (no[pos].r + no[pos].l) / 2;
    }
    if (no[pos].l == no[pos].r)
    {
        return ans;
    }
    int mid = (no[pos].r + no[pos].l) / 2;
    if (val <= mid)
    {
        ans += query(val, pos*2);
    }
    else
    {
        ans += query(val, pos*2+1);
    }
    return ans;
}
int main()
{
    /****************************/
    #ifndef ONLINE_JUDGE
    freopen("F:\\program study\\ACM\\1.in","r",stdin);
    freopen("F:\\program study\\ACM\\1.out","w",stdout);
    #endif
    /****************************/
    int cas;
    cin >> cas;
    while (cas--)
    {
        cin >> n >> m;
        bulid(1, MAX*2, 1);
        while (n--)
        {
            cin >> beg >> end;
            insert(beg+MAX, end+MAX, 1);
        }
        while (m--)
        {
            int t;
            cin >> t;
            cout << query(t+MAX, 1) << endl;
        }
    }
    /****************************/
    #ifndef ONLIINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    /****************************/
    return 0;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值