菜鸟系列——划分树
2015-06-18 00:36
337 查看
做回菜鸟,老老实实重新学起:
划分树
数据结构;求k大值及左右和模版:
#define N 123456 int sorted ={0}; //对原集合中元素排序后的值 int val[20] ={0}; //val记录第k层当前位置的值 int num[20] ={0}; //记录元素所在区间当前位置前的元素进入到左子树的个数 int lnum, rnum; //询问区间里面k-th数左侧和右侧的数的个数 long long sum[20] ={0}; //记录比当前元素小的元素的和 long long lsum, rsum; //询问区间里面k-th数左侧数之和与右侧数之和 void build(int l, int r, int d) { if (l == r) return ; int mid = (l + r) >> 1; int same = mid - l + 1; for (int i=l; i<=r; i++) if (val[d][i] > sorted[mid]) same--; int lp = l, rp = mid+1; for (int i=l; i<=r; i++) { if (i == l) { num[d][i] = 0; sum[d][i] = 0; } else { num[d][i] = num[d][i-1]; sum[d][i] = sum[d][i-1]; } if (val[d][i] > sorted[mid]) { num[d][i]++; sum[d][i] += val[d][i]; val[d+1][lp++] = val[d][i]; } else if (val[d][i] < sorted[mid]) val[d+1][rp++] = val[d][i]; else { if (same) { same--; num[d][i]++; sum[d][i] += val[d][i]; val[d+1][lp++] = val[d][i]; } else val[d+1][rp++] = val[d][i]; } } build(l, mid, d+1); build(mid+1, r, d+1); } int query(int a, int b, int k, int l, int r, int d) { if (a == b) return val[d][a]; int mid = (l + r) >> 1; int s, ss; long long sss; if (a == l) { s = num[d][b]; ss = 0; sss = sum[d][b]; } else { s = num[d][b] - num[d][a-1]; ss = num[d][a-1]; sss = sum[d][b] - sum[d][a-1]; } if (s >= k) { a = l + ss; b = l + ss + s - 1; return query(a, b, k, l, mid, d+1); } else { lnum += s; lsum += sss; a = mid+1 + a - l - ss; b = mid+1 + b - l - num[d][b]; return query(a, b, k-s, mid+1, r, d+1); } } bool cmp(int a,int b) { return a>b; } void solve(int n,int m) { long long s ={0}; for(int i=1;i<=n;i++) { scanf("%d",&sorted[i]); val[0][i] = sorted[i]; s[i] = s[i-1] + sorted[i]; } printf("\n"); sort(sorted+1,sorted+1+n,cmp); build(1,n,0); int x,y,k,res; while(m--) { scanf("%d%d%d",&x,&y,&k); lsum = lnum = 0; res = query(x,y,k,1,n,0); printf("%d ",res); //输出第k大值 rnum = y-x+1 - lnum; rsum = s[y] - s[x-1] - lsum - res; printf("%lld %lld\n",lsum,rsum); //区间内比第k大值小的和大的值的和; } }
eg:
题目参考:/article/2498566.html
POJ 2104 k-th number
http://poj.org/problem?id=2104题意:
求区间内k小值;思路:
直接划分树,求第k小值;code:
#define N 123456 int sorted ={0}; int val[20] ={0}; int num[20] ={0}; int lnum, rnum; long long sum[20] ={0}; long long lsum, rsum; void build(int l, int r, int d) { if (l == r) return ; int mid = (l + r) >> 1; int same = mid - l + 1; for (int i=l; i<=r; i++) if (val[d][i] < sorted[mid]) same--; int lp = l, rp = mid+1; for (int i=l; i<=r; i++) { if (i == l) { num[d][i] = 0; sum[d][i] = 0; } else { num[d][i] = num[d][i-1]; sum[d][i] = sum[d][i-1]; } if (val[d][i] < sorted[mid]) { num[d][i]++; sum[d][i] += val[d][i]; val[d+1][lp++] = val[d][i]; } else if (val[d][i] > sorted[mid]) val[d+1][rp++] = val[d][i]; else { if (same) { same--; num[d][i]++; sum[d][i] += val[d][i]; val[d+1][lp++] = val[d][i]; } else val[d+1][rp++] = val[d][i]; } } build(l, mid, d+1); build(mid+1, r, d+1); } int query(int a, int b, int k, int l, int r, int d) { if (a == b) return val[d][a]; int mid = (l + r) >> 1; int s, ss; long long sss; if (a == l) { s = num[d][b]; ss = 0; sss = sum[d][b]; } else { s = num[d][b] - num[d][a-1]; ss = num[d][a-1]; sss = sum[d][b] - sum[d][a-1]; } if (s >= k) { a = l + ss; b = l + ss + s - 1; return query(a, b, k, l, mid, d+1); } else { lnum += s; lsum += sss; a = mid+1 + a - l - ss; b = mid+1 + b - l - num[d][b]; return query(a, b, k-s, mid+1, r, d+1); } } bool cmp(int a,int b) { return a<b; } void solve(int n,int m) { for(int i=1;i<=n;i++) { scanf("%d",&sorted[i]); val[0][i] = sorted[i]; } sort(sorted+1,sorted+1+n,cmp); build(1,n,0); int x,y,k,res; while(m--) { scanf("%d%d%d",&x,&y,&k); res = query(x,y,k,1,n,0); printf("%d\n",res); } } int main() { int n, m; #ifndef ONLINE_JUDGE freopen("test.txt","r",stdin); #endif scanf("%d%d",&n,&m); solve(n,m); return 0; }
HDU 3473 Minimum Sum
http://acm.hdu.edu.cn/showproblem.php?pid=3473题意:
求区间内sum(x-xi)的最小值;x属于该区间;思路:
找到区间内中位数即可,求区间内中位数,记录区间内大于和小于中位数的数的和,差值加减多余的中位数的值就是答案了;code:
#define N 123456 int sorted ={0}; int val[20] ={0}; int num[20] ={0}; int lnum, rnum; long long sum[20] ={0}; long long lsum, rsum; void build(int l, int r, int d) { if (l == r) return ; int mid = (l + r) >> 1; int same = mid - l + 1; for (int i=l; i<=r; i++) if (val[d][i] < sorted[mid]) same--; int lp = l, rp = mid+1; for (int i=l; i<=r; i++) { if (i == l) { num[d][i] = 0; sum[d][i] = 0; } else { num[d][i] = num[d][i-1]; sum[d][i] = sum[d][i-1]; } if (val[d][i] < sorted[mid]) { num[d][i]++; sum[d][i] += val[d][i]; val[d+1][lp++] = val[d][i]; } else if (val[d][i] > sorted[mid]) val[d+1][rp++] = val[d][i]; else { if (same) { same--; num[d][i]++; sum[d][i] += val[d][i]; val[d+1][lp++] = val[d][i]; } else val[d+1][rp++] = val[d][i]; } } build(l, mid, d+1); build(mid+1, r, d+1); } int query(int a, int b, int k, int l, int r, int d) { if (a == b) return val[d][a]; int mid = (l + r) >> 1; int s, ss; long long sss; if (a == l) { s = num[d][b]; ss = 0; sss = sum[d][b]; } else { s = num[d][b] - num[d][a-1]; ss = num[d][a-1]; sss = sum[d][b] - sum[d][a-1]; } if (s >= k) { a = l + ss; b = l + ss + s - 1; return query(a, b, k, l, mid, d+1); } else { lnum += s; lsum += sss; a = mid+1 + a - l - ss; b = mid+1 + b - l - num[d][b]; return query(a, b, k-s, mid+1, r, d+1); } } bool cmp(int a,int b) { return a<b; } void solve(int n,int m) { long long s ={0}; for(int i=1;i<=n;i++) { scanf("%d",&sorted[i]); val[0][i] = sorted[i]; s[i] = s[i-1] + sorted[i]; } scanf("%d",&m); sort(sorted+1,sorted+1+n,cmp); build(1,n,0); int x,y,k,res; while(m--) { scanf("%d%d",&x,&y); x++,y++; k = (y-x+2)>>1; lsum = lnum = 0; res = query(x,y,k,1,n,0); rnum = y-x+1 - lnum; rsum = s[y] - s[x-1] - lsum; printf("%lld\n",(long long)(rsum-lsum+(lnum-rnum)*res)); //区间内比第k大值小的和大的值的和; } printf("\n"); } int main() { int k,kk,n,m; #ifndef ONLINE_JUDGE freopen("test.txt","r",stdin); #endif scanf("%d",&k); kk=0; while(k--) { printf("Case #%d:\n",++kk); scanf("%d",&n); solve(n,0); } return 0; }
相关文章推荐
- Python Show-Me-the-Code 第 0022 题 批量图片处理2
- 开源视频会议bigbluebutton开发(5)——开发web端,red5应用,桌面共享
- 开源视频会议bigbluebutton开发(5)——开发web端,red5应用,桌面共享
- Mysql DELETE删除除了最新的1000条记录的写法
- C++静态变量对象的建立和删除,兼论MFC开始运行的起点(全局对象)
- 开源视频会议bigbluebutton开发(4)——构建开发环境,客户端开发
- mvc+linq+EF对数据表的查删改
- php面向对象基础概念(接口)
- 开源视频会议bigbluebutton开发(4)——构建开发环境,客户端开发
- javabean实体类对象转为Map类型对象的方法
- 网络攻击常用技术
- kafka技术分享系列(目录索引)
- 理解xib(nib)、File’s Owner、First Responder、outlet、action等概念
- 开源视频会议bigbluebutton开发(3)——架构体系图
- jquery动画
- WinForm修改App.config配置文件功能
- 一年的路
- 我对DataFrame的理解(Spark)
- cv and deep learing blog & lecture
- KAFKA分布式消息系统