数状数组
2010-11-14 00:30
176 查看
树状数组不用多讲了,网上有关于这方面的内容很多,找找都是一大片,而且也不是很难,去学一下就可以很快领悟,至于怎么用,这就需要大量的做题了!
先提个注意点,由于Lowbit(0) = 0,这会导致x递增的那条路径发生死循环,所有当树状数组中可能出现0时,我们都全部加一,这样可以避免0带来的麻烦~~
简单:
POJ 2299 Ultra-QuickSort
http://acm.pku.edu.cn/JudgeOnline/problem?id=2299
求逆序数,可以用经典的归并排序做,也是基本的树状数组题目。
因为a[i]比较大,但只有最多500000个,所以要离散化。
逆序数就是求前面的数比后面的数大的次数。从后往前看就是求后面比前小的数的个数。用树状数组!c[i]表示比i的值小的个数。
代码
先提个注意点,由于Lowbit(0) = 0,这会导致x递增的那条路径发生死循环,所有当树状数组中可能出现0时,我们都全部加一,这样可以避免0带来的麻烦~~
简单:
POJ 2299 Ultra-QuickSort
http://acm.pku.edu.cn/JudgeOnline/problem?id=2299
求逆序数,可以用经典的归并排序做,也是基本的树状数组题目。
因为a[i]比较大,但只有最多500000个,所以要离散化。
逆序数就是求前面的数比后面的数大的次数。从后往前看就是求后面比前小的数的个数。用树状数组!c[i]表示比i的值小的个数。
代码
#include <iostream> #include <algorithm> using namespace std; #define maxn 200005 struct node { int x; int y; int LeftPoint; //正左边的点数 int RightPoint; //正右边的点数 int UpPoint; //正上方的点数 int DownPoint; //正下方的点数 int LargeY; //比该点Y大的数的数目 }p[maxn]; int C[maxn]; int BL,TL,TR,BR; /*对第j个点的四块内的点数 BL = Getsum(p[j].y) - p[j].LeftPoint - p[j].DownPoint; TL = j - p[j].LeftPoint - p[j].DownPoint - BL; TR = p[j].LargeY - TL - p[j].UpPoint; BR = n - j - 1 - TR - p[j].RightPoint - p[j].UpPoint; */ struct node1 { int Stan; int Ollie; }V[maxn]; bool cmp(node a,node b) { if(a.x == b.x) return a.y < b.y; return a.x < b.x; } bool cmp2(node a,node b) { if(a.y == b.y) return a.x < b.x; return a.y < b.y; } bool cmp3(node1 a,node1 b) { if(a.Stan == b.Stan) return a.Ollie < b.Ollie; return a.Stan > b.Stan; } //bool cmp1(node a,node b){return a.x < b.x;} int lowb(int t) { return t&(-t); } void Updata(int i) { while(i<maxn) { C[i] += 1; i += lowb(i); } } int Getsum(int i) { int s = 0; while(i>0) { s += C[i]; i -= lowb(i); } return s; } int main() { int i,j,k; int n,num; while(scanf("%d",&n)!=EOF && n!=0) { memset(C,0,sizeof(C)); for(i=0;i<n;i++) { scanf("%d%d",&p[i].x,&p[i].y); } sort(p,p+n,cmp); //X轴离散化 for(num=1,i=0;i<n;num++) { for(j=i+1;j<n;j++) { if(p[i].x != p[j].x) break; } for(k=i;k<j;k++) { p[k].UpPoint = j-1-k; p[k].DownPoint = k - i; p[k].x = num; } i = j; } sort(p,p+n,cmp2);//Y轴离散化 for(num=1,i=0;i<n;num++) { for(j=i+1;j<n;j++) { if(p[i].y != p[j].y) break; } for(k=i;k<j;k++) { p[k].LeftPoint = k - i; p[k].RightPoint = j-1-k; p[k].y = num; p[k].LargeY = n - j; } i = j; } sort(p,p+n,cmp); for(num=0,i=0;i<n;num++) { int Stan_num = 0x7fffffff; int Ollie_num = 0; for(j=i;j<n;j++) { if(p[j].x != p[i].x) break; BL = Getsum(p[j].y) - p[j].LeftPoint - p[j].DownPoint; TL = j - p[j].LeftPoint - p[j].DownPoint - BL; TR = p[j].LargeY - TL - p[j].UpPoint; BR = n - j - 1 - TR - p[j].RightPoint - p[j].UpPoint; if(TL + BR > Ollie_num) { Stan_num = BL + TR; Ollie_num = TL + BR; } else if(TL + BR == Ollie_num) { if(BL + TR <= Stan_num) { Stan_num = BL + TR; } } Updata(p[j].y); } V[num].Ollie = Ollie_num; V[num].Stan = Stan_num; i = j; } sort(V,V+num,cmp3); printf("Stan: %d; Ollie:",V[0].Stan); for(i=0;i<num;i++) { if(V[i].Stan != V[0].Stan) break; if(V[i].Ollie == V[i-1].Ollie && i != 0) continue; printf(" %d",V[i].Ollie); } printf(";\n"); } //system("pause"); return 0; }
相关文章推荐
- UPC-5911 计数问题(二维数状数组)
- POJ 3616【数状数组求区间最大值 + 简单DP】
- hdu 5057 Argestes and Sequence (数状数组+离线处理)
- poj 2481 Cows(数状数组 或 线段树)
- BZOJ2120:数颜色(数状数组套主席树)(带修改的莫对)
- A Simple Problem with Integers(多个数状数组)
- poj2892 Tunnel Warfare(数状数组+二分)
- 数状数组
- 杭电acm 1166敌兵布阵(数状数组)
- HDU 2227 Find the nondecreasing subsequences (数状数组)
- 解释下关于数状数组区间更新、单点查询和区间更新、区间查询
- 2017年第0届浙江工业大学之江学院程序设计竞赛决赛—J(数状数组)
- codeforces 703D Mishka and Interesting sum(数状数组维护前缀)
- POJ 2299 再水一发数状数组求逆序数
- No Pain No Game(数状数组离线查询)
- hdu 1166数状数组
- 【poj2155】【二维数状数组】Matrix
- POJ1195 Mobile phones 二维数状数组
- Find the nondecreasing subsequences(数状数组+离散化+dp)
- poj 3298 数状数组