线段树专题2-(加强版线段树-可持续化线段树)主席树 orz! ------用于解决区间第k大的问题----xdoj-1216
poj-2104(区间第K大问题)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
struct T {
int ls;
int rs;
int sum;
};
const int N=1e5+;
T tri[*N];
int a[N],sort_a[N];
int rt[N];
int cnt;
int n,m;
void update (int l,int r,int rt1,int &rt2,int pos) {
rt2=++cnt;
tri[rt2]=tri[rt1];
tri[rt2].sum++;// 在此处直接更新,就不用pushup了
if (l==r) return ;
int mid=(l+r)/;
if (pos<=mid) update (l,mid,tri[rt1].ls,tri[rt2].ls,pos);
else update (mid+,r,tri[rt1].rs,tri[rt2].rs,pos);
return ;
}
int query (int l,int r,int rt1,int rt2,int k) {
if (l==r) return sort_a[l];
int mid=(l+r)/;
int sum=tri[tri[rt2].ls].sum-tri[tri[rt1].ls].sum;//我又出错了 sum应该是左子树的节点数 T_T !
if (k<=sum) return query (l,mid,tri[rt1].ls,tri[rt2].ls,k);
else return query (mid+,r,tri[rt1].rs,tri[rt2].rs,k-sum);
}
int main ()
{
scanf ("%d %d",&n,&m);
for (int i=;i<=n;i++) {
scanf ("%d",&a[i]);
sort_a[i]=a[i];
}
sort (sort_a+,sort_a++n);
int num=;
for (int i=;i<=n;i++) {
if (sort_a[i]!=sort_a[i-])
sort_a[++num]=sort_a[i];//离散化
}
rt[]=cnt=;
tri[].sum=tri[].ls=tri[].rs=;
for (int i=;i<=n;i++) {
int pos=lower_bound (sort_a+,sort_a++num,a[i])-sort_a;
update (,num,rt[i-],rt[i],pos);
}
for (int i=;i<=m;i++) {
int x,y,k;
scanf ("%d %d %d",&x,&y,&k);
printf("%d\n",query (,num,rt[x-],rt[y],k));
}
return ;
}
NO.2 HDOJ-4417(主席数的区间求和)
#include<cstdio>
#include<algorithm>
const int N=1e5+;
using namespace std;
struct node {
int ls;
int rs;
int sum;
};
node tri[*N];
int rt[N];
int a[N],sort_a[N+];
int cnt,n,m,x,y,k;
void updata (int l,int r,int rt1,int& rt2,int pos) {
rt2=(++cnt);
tri[rt2]=tri[rt1];
tri[rt2].sum++;
if (l==r) return ;
int mid=(l+r)/;
if (pos<=mid) updata(l,mid,tri[rt1].ls,tri[rt2].ls,pos);
else updata(mid+,r,tri[rt1].rs,tri[rt2].rs,pos);
return ;
}
int query (int l,int r,int L,int R,int rt1,int rt2) {
if (r<L||l>R) return ;
if (l>=L&&r<=R) return tri[rt2].sum-tri[rt1].sum;
int mid=(l+r)/;
int t1=query(l,mid,L,R,tri[rt1].ls,tri[rt2].ls);
int t2=query(mid+,r,L,R,tri[rt1].rs,tri[rt2].rs);
return t1+t2;
}
int main ()
{
int T;
int tt=;
scanf ("%d",&T);
while (T--) {
printf("Case %d:\n",tt++);
scanf ("%d %d",&n,&m);
for (int i=;i<=n;i++) {
scanf ("%d",&a[i]);
sort_a[i]=a[i];
}
sort(sort_a+,sort_a++n);
int num=;
for (int i=;i<=n;i++) {
if (sort_a[i]!=sort_a[num])
sort_a[++num]=sort_a[i];
}
cnt=;
rt[]=;
tri[].ls=tri[].rs=tri[].sum=;
for (int i=;i<=n;i++) {
int pos=lower_bound(sort_a+,sort_a++num,a[i])-sort_a;
updata(,num,rt[i-],rt[i],pos);
}
for (int i=;i<=m;i++) {
scanf ("%d %d %d",&x,&y,&k);
int t=lower_bound(sort_a+,sort_a++num,k)-sort_a;
if (t>num||sort_a[t]>k) t--;// 这个好 找最后一个小于等于k的数
int ans=query (,num,,t,rt[x],rt[y+]);// 因为题目从0开始计数
printf("%d\n",ans);
}
}
return ;
}
No.3 xdoj-1216(子树第k小)——dfs+主席树
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e5+;
struct T{
int ls;
int rs;
int sum;
};
vector < vector <int> > g(N);
T tri[N*];
int rt[N],b[N],sort_b[N];
int in[N],out[N];
int val[N];
int cnt,num;
int n,q;
int x,k;
void dfs (int id,int pre) {
num++;
sort_b[num]=b[num]=val[id];
in[id]=num;
for (int i=;i<g[id].size();i++) {
int next=g[id][i];
if (next==pre) continue;
dfs (next,id);
}
out[id]=num;
}
void updata (int l,int r,int pos,int rt1,int& rt2) {
cnt++;
rt2=cnt;
tri[cnt]=tri[rt1];
tri[cnt].sum++;
if (l==r) return ;
int mid=(l+r)/;
if (pos<=mid) updata (l,mid,pos,tri[rt1].ls,tri[rt2].ls);
else updata (mid+,r,pos,tri[rt1].rs,tri[rt2].rs);
return ;
}
int query (int l,int r,int k,int rt1,int rt2) {
if (l==r) return l;
int mid=(l+r)/;
int ans;
int sum=tri[tri[rt2].ls].sum-tri[tri[rt1].ls].sum;
if (k<=sum) ans=query (l,mid,k,tri[rt1].ls,tri[rt2].ls);
else ans=query (mid+,r,k-sum,tri[rt1].rs,tri[rt2].rs);
return ans;
}
int main ()
{
while (scanf ("%d",&n)!=EOF) {
for (int i=;i<=n;i++) g[i].clear();
for (int i=;i<=n;i++)
scanf ("%d",&val[i]);
int u,v;
for (int i=;i<=n-;i++) {
scanf ("%d %d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
num=;
dfs (,-);// 按理说有根树 直接dfs(1)就可以了可是这样答案是不对的 是我理解错了还是数据有问题呢
sort(sort_b+,sort_b++n);
int nn=;
for (int i=;i<=n;i++)
if (sort_b[i]!=sort_b[nn])
sort_b[++nn]=sort_b[i];
rt[]=;
tri[].rs=tri[].ls=tri[].sum=;
cnt=;
for (int i=;i<=n;i++) {
int pos=lower_bound(sort_b+,sort_b++nn,b[i])-sort_b;
updata(,nn,pos,rt[i-],rt[i]);
}
scanf ("%d",&q);
for (int i=;i<=q;i++) {
scanf ("%d %d",&x,&k);
int ans=query (,nn,k,rt[in[x]-],rt[out[x]]);
printf ("%d\n",sort_b[ans]);
}
}
return ;
}
线段树专题2-(加强版线段树-可持续化线段树)主席树 orz! ------用于解决区间第k大的问题----xdoj-1216的更多相关文章
- POJ 2104 HDU 2665 主席树 解决区间第K大
两道题都是区间第K大询问,数据规模基本相同. 解决这种问题, 可以采用平方划分(块状表)复杂度也可以接受,但是实际表现比主席树差得多. 这里大致讲一下我对主席树的理解. 首先,如果对于某个区间[L,R ...
- 可持久化线段树(主席树)(图文并茂详解)【poj2104】【区间第k大】
[pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=63740442 向大(hei)佬(e)实力学(di ...
- Permutation UVA - 11525(值域树状数组,树状数组区间第k大(离线),log方,log)(值域线段树第k大)
Permutation UVA - 11525 看康托展开 题目给出的式子(n=s[1]*(k-1)!+s[2]*(k-2)!+...+s[k]*0!)非常像逆康托展开(将n个数的所有排列按字典序排序 ...
- 可持久化线段树(主席树)——静态区间第k大
主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...
- 【BZOJ3551】Peaks加强版(Kruskal重构树,主席树)
[BZOJ3551]Peaks加强版(Kruskal重构树,主席树) 题面 BZOJ Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相 ...
- 主席树入门(区间第k大)
主席树入门 时隔5个月,我又来填主席树的坑了,现在才发现学算法真的要懂了之后,再自己调试,慢慢写出来,如果不懂,就只会按照代码敲,是不会有任何提升的,都不如不照着敲. 所以搞算法一定要弄清原理,和代码 ...
- 【ZOJ2112】【整体二分+树状数组】带修改区间第k大
The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with t ...
- POJ2104-- K-th Number(主席树静态区间第k大)
[转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段 ...
- hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)
题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...
随机推荐
- lombok @Slf4j注解
背景知道有这么个东西,是因为项目中用到了@Slf4j注解. lombok库提供了一些注解来简化java代码 官网:http://projectlombok.org/ 查看lombok所有api:htt ...
- ubuntu下的网速限制软件wondershaper (2011-09-18 00:00:00)转载▼
上网或下载的时候我们常常希望网速快一点,但有时我们也需要限制网速,在ubuntu系统下,可以使用wondershaper,不仅可以限制下载速度还可以限制上传速度. 安装好之后,需要使用终端取得管理员权 ...
- VIM编辑配置文件基本操作
vim /etc/apt/sources.list 按insert键进入编辑状态 编辑完成以后按ESC退出编辑状态 输入 ":"进入命令状态,常用命令: 1.W:write ,写 ...
- 利用awk处理学生成绩问题(难度较大)
学生成绩表单如下: Name,Team,First Test, Second Test, Third Test Tom,Red,,, Joe,Green,,, Maria,Blue,,, Fred,B ...
- zookeeper集群环境搭建(纯zookeeper)
1.首先在三台机子上放上zookeeper的解压包,解压. 然后的话zookeeper是依赖于jdk的,那么也应该安装jdk,这里不详细说明了. mv zookeeper-3.4.5 zookeepe ...
- 【原创】imread () 函数 读入图片的例子
Reference Links Opencv+ qt5.1 完美配置 - 脚踏实地 - 博客频道 - CSDN.NET http://blog.csdn.net/xiaojidan2011/arti ...
- ubuntu 命令行卸载并清理软件
1.删除软件 方法一.如果你知道要删除软件的具体名称,可以使用 sudo apt-get remove --purge 软件名称 sudo apt-get autoremove --purge 软件名 ...
- css文件 如何使背景图片大小适应div的大小
对背景图片设置属性:background-size:cover;可以实现背景图片适应div的大小. background-size有3个属性: auto:当使用该属性的时候,背景图片将保持100% 的 ...
- 6.1 C++ string类型变量的定义以及输入与输出
参考:http://www.weixueyuan.net/view/6389.html 总结: 在C++中提供了一个型的内建数据类型string,该数据类型可以替代C语言中char数组. 与C风格的c ...
- Docker小白从零入门到实战系列【二】
1.安装好Centos 7 2.关闭SELINUX sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/configsetenfo ...