1、求区间第K大

HDU2665 Kth number

/*划分树
查询区间第K大 */ #include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std; #define ll long long
const int MAXN=100009;
int tree[21][MAXN];//表示每层每个位置的值
int sorted[MAXN];//已经排序好的数
int toleft[21][MAXN];//toleft[p][i]表示第i层从1到i有多少数划入左边 /*建树
same表示等于sorted[mid]的个数,初始化为mid-l+1,扫描后每出现一个更小的值,减1
所以same表示要被分入左边等于中间值的个数
建树分三种情况:
1、如果tree[[dep][i]<sorted[mid]划入左边
2、如果tree[dep][i]==sorted[mid],same>0的话划入左边
3、否则就是划入右边
*/ void build(int l,int r,int dep)
{
if(l==r)return;
int mid=(l+r)>>1;
int same=mid-l+1;
for(int i=l;i<=r;i++)
{
if(tree[dep][i]<sorted[mid])
{
same--;
}
}
int lpos=l;
int rpos=mid+1;
for(int i=l;i<=r;i++)
{
if(tree[dep][i]<sorted[mid])
tree[dep+1][lpos++]=tree[dep][i];
else if(tree[dep][i]==sorted[mid]&&same)
{
tree[dep+1][lpos++]=tree[dep][i];
same--;
}
else
{
tree[dep+1][rpos++]=tree[dep][i];
}
toleft[dep][i]=toleft[dep][l-1]+lpos-l;
}
build(l,mid,dep+1);
build(mid+1,r,dep+1);
}
/*查询操作
查询区间第K大值,[L,R]是大区间,[l,r]是要查询的小区间
cnt记录划入左边的个数
1、如果cnt>=k,说明第K大在左子树
2、否则,说明第K大在右子树
*/
int query(int L,int R,int l,int r,int dep,int k)
{
if(l==r)return tree[dep][l];
int mid=(L+R)>>1;
int cnt=toleft[dep][r]-toleft[dep][l-1];
if(cnt>=k)
{
int newl=L+toleft[dep][l-1]-toleft[dep][L-1];
int newr=newl+cnt-1;
return query(L,mid,newl,newr,dep+1,k);
}
else
{
int newr=r+toleft[dep][R]-toleft[dep][r];
int newl=newr-(r-l-cnt);
return query(mid+1,R,newl,newr,dep+1,k-cnt);
}
} int main()
{
int n,m;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++)
{
scanf("%d",&tree[0][i]);
sorted[i]=tree[0][i];
}
sort(sorted+1,sorted+n+1);
build(1,n,0);
int s,t,k;
while(m--)
{
scanf("%d%d%d",&s,&t,&k);
printf("%d\n",query(1,n,s,t,0,k));
}
}
return 0;
}

2、查找中位数

http://acm.hdu.edu.cn/showproblem.php?pid=3473【HDU3473】

找出中间的那个x,计算公式为x*(r-l+1)/2)-(sum[l,mid]+x)+(sum[l,r]-sum[l,mid]-x)-((r-l-前一半-1+1)/2)*x

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1000000001
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = 100010;
int num[20][MAXN],cnt[20][MAXN],sor[MAXN],n,leftnum;
ll sum[20][MAXN],leftsum,all[MAXN];//sum记录第d层 第i个数之前小于sor[m]的和
void build(int l,int r,int d)
{
if(l == r){
return ;
}
int m = (l + r) >> 1;
int same_m = m - l + 1;
for(int i = l; i <= r; i++){
if(num[d][i] < sor[m])same_m --;
}
int cnt_small = 0;
int pl,pr;
ll val = 0;
pl = l,pr = m + 1;
for(int i = l; i <= r; i++){
if(num[d][i] < sor[m]){
cnt_small ++;
val += num[d][i];
sum[d][i] = val;
cnt[d][i] = cnt_small;
num[d+1][pl++] = num[d][i];
}
else if(num[d][i] == sor[m] && same_m){
same_m --;
cnt_small ++;
val += num[d][i];
sum[d][i] = val;
cnt[d][i] = cnt_small;
num[d+1][pl++] = num[d][i];
}
else {
sum[d][i] = val;
cnt[d][i] = cnt_small;
num[d+1][pr++] = num[d][i];
}
}
build(l,m,d+1);
build(m+1,r,d+1);
}
ll query(int L,int R,int k,int l,int r,int d)
{
if(l == r){
return num[d][l];
}
int m = (l + r) >> 1;
int s,ss;
ll val = 0;
if(l == L)s = 0, val = sum[d][R];
else s = cnt[d][L-1], val = sum[d][R] - sum[d][L-1];
ss = cnt[d][R] - s;
if(ss >= k){
int newl = l + s;
int newr = l + s + ss - 1;
return query(newl,newr,k,l,m,d+1);
}
else {
leftnum += ss;//进入左孩子不用处理,进入右孩子时 就要加上左孩子的值
leftsum += val;
int a = L - l - s;
int b = R - L + 1 - ss;
int newl = m + 1 + a;
int newr = m + 1 + a + b - 1;
return query(newl,newr,k - ss,m+1,r,d+1);
}
}
int main()
{
int t,ff = 0;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
memset(all,0,sizeof(all));
memset(num,0,sizeof(num));
for(int i = 1; i <= n; i++){
scanf("%d",&num[1][i]);
sor[i] = num[1][i];
all[i] = all[i-1] + sor[i];
}
sort(sor + 1,sor + n + 1);
build(1,n,1);
int q,x,y;
scanf("%d",&q);
printf("Case #%d:\n",++ff);
while(q--){
scanf("%d%d",&x,&y);
x += 1;
y += 1;
int len = (y - x + 1);
ll tp;
leftnum = 0;
leftsum = 0;
if(len % 2){
int k = (len + 1) >> 1;
tp = query(x,y,k,1,n,1);
}
else {
int k = len >> 1;
tp = query(x,y,k,1,n,1);
}
//cout<<tp<<‘ ‘<<leftnum<<‘ ‘<<leftsum<<‘ ‘<<all[y]<<‘ ‘<<all[x+leftnum]<<endl;
ll ans = tp * (leftnum + 1) - (leftsum + tp) + (all[y] - all[x - 1] - (leftsum + tp)) - (y - x + 1 - (leftnum + 1)) * tp;
printf("%lld\n",ans);
}
printf("\n");
}
return 0;
}

bryce1010专题训练——划分树的更多相关文章

  1. bryce1010专题训练——LCT&&树链剖分

    LCT&&树链剖分专题 参考: https://blog.csdn.net/forever_wjs/article/details/52116682

  2. bryce1010专题训练——线段树习题汇总

    一.区间查询,无单点更新 hdu2795 Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  3. bryce1010专题训练——Splay树

    Prob Hint BZOJ 3323 文艺平衡树 区间翻转 BZOJ 1251 序列终结者 区间翻转,询问最值 BZOJ 1895 supermemo 区间加,翻转,剪切,询问最值.点插入,删除. ...

  4. bryce1010专题训练——树状数组

    Bryce1010模板 1.一维树状数组 https://vjudge.net/contest/239647#problem/A[HDU1556] #include<bits/stdc++.h& ...

  5. bryce1010专题训练——CDQ分治

    Bryce1010模板 CDQ分治 1.与普通分治的区别 普通分治中,每一个子问题只解决它本身(可以说是封闭的) 分治中,对于划分出来的两个子问题,前一个子问题用来解决后一个子问题而不是它本身 2.试 ...

  6. Leedcode算法专题训练(树)

    递归 一棵树要么是空树,要么有两个指针,每个指针指向一棵树.树是一种递归结构,很多树的问题可以使用递归来处理. 1. 树的高度 104. Maximum Depth of Binary Tree (E ...

  7. bryce1010专题训练——LCA

    1.Targan算法(离线) http://poj.org/problem?id=1470 /*伪代码 Tarjan(u)//marge和find为并查集合并函数和查找函数 { for each(u, ...

  8. dp专题训练

    ****************************************************************************************** 动态规划 专题训练 ...

  9. DP专题训练之HDU 2955 Robberies

    打算专题训练下DP,做一道帖一道吧~~现在的代码风格完全变了~~大概是懒了.所以.将就着看吧~哈哈 Description The aspiring Roy the Robber has seen a ...

随机推荐

  1. JavaScript提高:001:ASP.NET使用easy UI

    jQuery EasyUI是一组基于jQuery的UI插件集合.能够简洁的开发出功能多内容丰富的界面,而不须要开发人员自己费力的写那些复杂的js代码.本文简介在ASP.NET开发中引用这些js文件和样 ...

  2. 图像处理之 opencv 学习---矩阵的操作

    OpenCV的一些操作,如生成随机矩阵,高斯矩阵,矩阵相乘之类的 /*功能:说明矩阵的一些操作方法*/#include "cv.h"//该头文件包含了#include " ...

  3. android 编程小技巧(持续中)

    first:     Intent跳转一般存用于Activity类,可是若要在非activity类里跳转的话,解决方法是在startActivity(intent)前加mContext即上下文,终于为 ...

  4. 查询历史使用过的命令并使用(history)

    一.什么是history 在bash功能中.它能记忆使用过的命令,这个功能最大的优点就是能够查询以前做过的举动.从而能够知道你的执行步骤.那么就能够追踪你曾下达过的命令.以作为除错的工具. 二.His ...

  5. git常用知识笔记

    学习资料: http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 http://codi ...

  6. 增加实时性的异常url检测

    技能点: 搭建服务器.restfulapi 在py脚本中调取另一个脚本执行

  7. Java,如何获取文件的MD5值

    MessageDigest类封装得很不错,简单易用 不多说,直接上代码 import java.io.FileInputStream;import java.security.MessageDiges ...

  8. C/C++ 操作符优先级

    不能光转贴,有空要熟悉之后,要写点心得.现在发现 . 的优先级确实很高. C: Precedence Operator Description Associativity 1 ++ -- Suffix ...

  9. node-orm2

    最近应老大要求,对orm2进行再一步封装,所以记录下封装和使用心得(文中数据库:mysql). 数据库连接 var orm = require("orm"); orm.connec ...

  10. 微信小程序 navigateTo 传对象参数

    当微信小程序navigateTo传入参数是个object时,请使用JSON.strtingify将object转化为字符串,代码如下: wx.navigateTo({ url: '../sendChe ...