这次做了一些线段树的题,所以来发个博客
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;
}