线段树专题

这次做了一些线段树的题,所以来发个博客

 

 

hdu 1541  Stars

题意: 给你N个星星的坐标,求第i个星星的的LEVEL  ,一个星星的LEVEL= 该星星的左下角的星星数目+1

其中 输入是按每个星星的Y坐标从小到大的

 

因为第I个星星的Y是从小到大的, 所以第i个星星前的星星数目为 当前X坐标为[0,Xi ]之间的星星的数目

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 32000

struct node
{
	int l,r;
	int sum;
}a[4*maxn+5];

int ans[maxn+5];

void Build(int l, int r, int be)
{
	a[be].l= l;
	a[be].r= r;
	a[be].sum= 0;
	if(l == r)
		return;
	int mid= (l + r)/2;	
	Build(l, mid, 2*be);
	Build(mid+1, r, 2*be+1);	
}

void Add(int num, int v, int n)
{
	if(v == a[n].l && v == a[n].r)
	{
		a[n].sum+= num;
		return;
	}
	int mid= (a[n].l + a[n].r)/ 2;
	if(v <= mid)
		Add(num, v, 2*n);
	else
		Add(num, v, 2*n+1);
	a[n].sum= a[2*n].sum + a[2*n+1].sum;		
}

int Qsum(int l, int r, int n)
{
	if(l == a[n].l && r == a[n].r)
		return a[n].sum;
	int mid= (a[n].l + a[n].r)/ 2;
	if(r <= mid)
		return	Qsum(l, r, 2*n);
	else if(l > mid)
		return	Qsum(l, r, 2*n+1);
	else
		return  Qsum(l, mid, 2*n) + Qsum(mid+1, r, 2*n+1);		
}	
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		Build(0,32000,1);
		memset(ans, 0, sizeof(ans));
		int xx, yy;
		for(int i= 1; i<= n; i++)
		{
			scanf("%d %d",&xx, &yy);
			ans[Qsum(0, xx, 1)]++;
			Add(1, xx, 1);	
		}
		for(int i= 0; i< n; i++)
			printf("%d\n",ans[i]);
	}
	return 0;
}



 

 

Poj 2418 Cows

这题和星星那道题差不多,只需要排一次序就和上题一样了

PS: 两个点相同的时候需要特判一下

代码:

 

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 100000

struct node
{
	int sum;
	int l, r;
}a[4*maxn+5];

struct point
{
	int x;
	int y;
	int pos;
}p[maxn+5];

int ans[maxn+5];

int cmp(point x, point y)
{
	if(x.y != y.y)
		return x.y > y.y;
	else return x.x < y.x;
}

void Build(int l, int r, int n)
{
	a[n].l= l;
	a[n].r= r;
	a[n].sum= 0;
	if(l == r)
		return;
	int mid= ( a[n].l + a[n].r)/2;
	Build(l, mid, 2*n);
	Build(mid+1, r, 2*n+1);	
}

void add(int v, int n)
{
	if(v == a[n].l && v == a[n].r)
	{
		a[n].sum++;
		return;
	}
	int mid= (a[n].l + a[n].r)/2;
	if(v<= mid)
		add(v, 2*n);
	else
		add(v, 2*n+1);
	a[n].sum= a[2*n].sum + a[2*n+1].sum;		
}

int Qsum(int l, int r, int n)
{
	if(l == a[n].l && r == a[n].r)
		return a[n].sum;
	
	int mid= ( a[n].l + a[n].r ) /2;
	if(r<= mid)
		return Qsum(l, r, 2*n);
	else if(l > mid)
		return Qsum(l, r, 2*n+1);
	else
		return 	Qsum(l, mid, 2*n) + Qsum(mid+1, r, 2*n +1);		 	
}

int main()
{
	int n;
	while(scanf("%d",&n)!=EOF && n)
	{
		//int xx, yy;
		Build(0, 100000, 1);
		//printf("hehe\n");
		for(int i= 1; i<= n; i++)
		{
			scanf("%d %d",&p[i].x,&p[i].y);
			p[i].pos= i;
		}
		sort(p+1, p+n+1, cmp);
		for(int i= 1; i<= n; i++)
		{
			if( p[i].x == p[i-1].x && p[i].y == p[i-1].y)
				ans[p[i].pos]= ans[p[i-1].pos];  //如果两个点一模一样,则ans等于上一个点的ans; 
			else
				ans[p[i].pos]= Qsum(0, p[i].x, 1);
			add(p[i].x, 1);
		}
		printf("%d",ans[1]);
		for(int i= 2; i<= n; i++)
			printf(" %d",ans[i]);
		printf("\n");		
	}
return 0;
}


Poj 2299 Ultra-QuickSort 

线段树+ 离散化

经典的求逆序对,不过有两个地方需要注意一下,因为数据无法用数组存储,所以要用到数据离散化

一,数据离散化第一个数需特判 ,不然当第一个数等于0时,离散化会出错

二,离散化过程需判断该数是否和前一个数相等,若相等则两数离散化后的结果也一样

 

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 500000
struct pp 
{
    int num, pos;
    int x;
}p[maxn+5];
struct node
{
    int num;
    int l, r; 
}a[4*maxn+5];
void Build (int l, int r, int n)
{
    a[n].l= l;
    a[n].r= r;
    a[n].num= 0;
    if(l == r)
        return;
    int mid= (a[n].l + a[n].r )/2;
    Build(l, mid, 2*n);
    Build(mid+1, r, 2*n+1);    
}
int Qsum(int l, int r, int n)
{
    if(l == a[n].l && r == a[n].r)
    {
        return a[n].num;
    }
    int mid= (a[n].l + a[n].r)/ 2;
    if(r<= mid)
        return Qsum(l, r, 2*n);
    else if(l > mid)
        return Qsum(l, r, 2*n+1);
    else
        return Qsum(l, mid, 2*n) + Qsum(mid+1, r, 2*n+1);         
}
void  Add(int v, int num, int n)
{
    if(v == a[n].l && v == a[n].r)
    {
        a[n].num+= num;
        return;
    } 
    int mid= (a[n].l + a[n].r)/ 2;
    if(v<= mid)
        Add(v, num, 2*n);
    else
        Add(v, num, 2*n+1);
    a[n].num= a[2*n].num + a[2*n+1].num;        
}
int cmp1(pp x, pp y)
{
    return x.num< y.num; 
}
int cmp2(pp x, pp y)
{
    return x.pos < y.pos; 
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF && n)
    {
        Build(1, n, 1);
        for(int i= 1; i<= n; i++)
        {
            scanf("%d",&p[i].num);
            p[i].pos= i;
        }
        sort(p+1, p+1+n, cmp1);
        
        p[1].x= 1; // 此处需预处理不然当p[1].num= 0时,p[1].x会出错 
        for(int i= 2; i<= n; i++)
            if(p[i].num == p[i-1].num)
                p[i].x= p[i-1].x;
            else
                p[i].x= i;      
        sort(p+1, p+1+n, cmp2);    
        long long ans= 0; 
        for(int i= 1; i<= n; i++)
        {
            ans+= Qsum(1, n, 1) - Qsum(1, p[i].x, 1);    
            Add(p[i].x, 1, 1);    
        }        
        printf("%lld\n", ans);
    }
    return 0;
}


 

Poj 3067 Japan

和星星那题差不多

代码:

 

#include <stdio.h>
#include <string.h>
#include <algorithm>

using namespace std;
#define maxn 1000

struct point
{
	int x;
	int y;
}p[maxn*maxn +5];

struct node
{
	int l, r;
	int sum;
}a[4*maxn+5];

int cmp(point x, point y)
{
	if(x.x!= y.x)
		return x.x < y.x;
	return x.y < y.y;	
}

void Build(int l, int r, int n)
{
	a[n].l = l;
	a[n].r = r;
	a[n].sum = 0;
	if(l == r)
		return;
	int mid= (a[n].l + a[n].r)/ 2;
	Build(l, mid, 2*n);
	Build(mid+1, r, 2*n+1);	
}

void Add(int v,int num, int n)
{
	if(v == a[n].l && v == a[n].r)
	{
		a[n].sum+= num;
		return;
	}
	int mid= (a[n].l + a[n].r)/ 2;
	if(v<= mid)
		Add(v, num, 2*n);
	else 
		Add(v, num, 2*n+1);
	a[n].sum= a[2*n].sum + a[2*n+1].sum;			
}

int Qsum(int l, int r, int n)
{
	if(l == a[n].l && r == a[n].r)
		return a[n].sum;
	int mid= (a[n].l + a[n].r)/ 2;
	if(r<= mid)
		return Qsum(l, r, 2*n);
	else if(l> mid)
	 	return Qsum(l, r, 2*n+1);
	else
	 	return Qsum(l, mid, 2*n) + Qsum(mid+1, r, 2*n+1); 		
}

int main()
{
	int T;scanf("%d",&T);
	for(int t= 1; t<= T; t++)
	{
		int n, m , k;
		scanf("%d %d %d",&n,&m,&k);
		Build(1, m, 1);
		for(int i= 1; i<= k; i++)
			scanf("%d %d",&p[i].x, &p[i].y);
		sort(p+1, p+k+1, cmp);
		long long ans= 0;
		for(int i= 1; i<= k; i++)
		{
			ans+= Qsum(1, m, 1)- Qsum(1, p[i].y, 1);
			Add(p[i].y, 1, 1);
		}
		printf("Test case %d: %lld\n",t,ans);
	}
	return 0;
}

你可能感兴趣的:(数据结构)