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