2016夏季练习——线段树
2016-07-18 16:00
267 查看
来源:POJ2182
解释在注释里面
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 8000+10;
struct Tree{
int l,r;
int len;
Tree():len(0){}
};
int n;
int a[MAXN];
int ans[MAXN];
Tree tree[MAXN*4];
void build(int rt,int left,int right){
tree[rt].l=left;
tree[rt].r=right;
tree[rt].len=right-left+1;
if(left==right) return ;
int mid=(left+right)>>1;
build(rt<<1,left,mid);
build(rt<<1|1,mid+1,right);
}
int query(int rt,int tot){
tree[rt].len--;
//关键就是这一步!!!
//我们访问这个节点,也就意味着这个节点所表示的区间中有我需要的那个值
//那么我取走那个值的时候,对应后面的数就不能把这个节点数算在里面
//cout<<rt<<" "<<tree[rt].l<<" "<<tree[rt].r<<" "<<tree[rt].len<<" "<<tot<<endl;
if(tree[rt].l==tree[rt].r) {
//cout<<"leaves!!!"<<endl;
return tree[rt].l;
}
//下面是访问策略
//根据上面的分析可以知道
//结构中len的使用其实不能叫做len
//表示的是当前区间中小于r但是还没有被使用过的数字
//这样的话下面的这个就是显然的了
if(tot>tree[rt<<1].len) {
//cout<<"right"<<endl;
return query(rt<<1|1,tot-tree[rt<<1].len);
}
else {
//cout<<"left"<<endl;
return query(rt<<1,tot);
}
}
int main(){
scanf("%d",&n);
build(1,1,n);
memset(a,0,sizeof(a));
/*for(int i=1;i<=2*n-1;i++)
cout<<i<<" "<<tree[i].l<<" "<<tree[i].r<<" "<<tree[i].len<<endl;*/
for(int i=2;i<=n;i++){
scanf("%d",a+i);
}
//注意,我们最后一个数其实有着自己的性质:因为前面的所有数都已经出来了
//所以我们最后一个一定是a[i]+1
//这样,我们继续向前的时候,我们将遇到一个问题:
//我已经用过的这个数应该是怎么办?
//我们去query函数中看这个问题。
for(int i=n;i>0;i--){
//cout<<"n="<<i<<": a[i]="<<a[i]<<endl;
ans[i]=query(1,a[i]+1);
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<endl;
}
return 0;
}
解释在注释里面
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAXN = 8000+10;
struct Tree{
int l,r;
int len;
Tree():len(0){}
};
int n;
int a[MAXN];
int ans[MAXN];
Tree tree[MAXN*4];
void build(int rt,int left,int right){
tree[rt].l=left;
tree[rt].r=right;
tree[rt].len=right-left+1;
if(left==right) return ;
int mid=(left+right)>>1;
build(rt<<1,left,mid);
build(rt<<1|1,mid+1,right);
}
int query(int rt,int tot){
tree[rt].len--;
//关键就是这一步!!!
//我们访问这个节点,也就意味着这个节点所表示的区间中有我需要的那个值
//那么我取走那个值的时候,对应后面的数就不能把这个节点数算在里面
//cout<<rt<<" "<<tree[rt].l<<" "<<tree[rt].r<<" "<<tree[rt].len<<" "<<tot<<endl;
if(tree[rt].l==tree[rt].r) {
//cout<<"leaves!!!"<<endl;
return tree[rt].l;
}
//下面是访问策略
//根据上面的分析可以知道
//结构中len的使用其实不能叫做len
//表示的是当前区间中小于r但是还没有被使用过的数字
//这样的话下面的这个就是显然的了
if(tot>tree[rt<<1].len) {
//cout<<"right"<<endl;
return query(rt<<1|1,tot-tree[rt<<1].len);
}
else {
//cout<<"left"<<endl;
return query(rt<<1,tot);
}
}
int main(){
scanf("%d",&n);
build(1,1,n);
memset(a,0,sizeof(a));
/*for(int i=1;i<=2*n-1;i++)
cout<<i<<" "<<tree[i].l<<" "<<tree[i].r<<" "<<tree[i].len<<endl;*/
for(int i=2;i<=n;i++){
scanf("%d",a+i);
}
//注意,我们最后一个数其实有着自己的性质:因为前面的所有数都已经出来了
//所以我们最后一个一定是a[i]+1
//这样,我们继续向前的时候,我们将遇到一个问题:
//我已经用过的这个数应该是怎么办?
//我们去query函数中看这个问题。
for(int i=n;i>0;i--){
//cout<<"n="<<i<<": a[i]="<<a[i]<<endl;
ans[i]=query(1,a[i]+1);
}
for(int i=1;i<=n;i++){
cout<<ans[i]<<endl;
}
return 0;
}
相关文章推荐
- CSS ::selection伪类选择器
- 博客转移到https://m00z.github.io
- selenium2.0关于python的常用函数(二)
- RTMPdump(libRTMP) 源代码分析 3: AMF编码
- 79. Word Search
- 数据库服务器2块网卡,不同网段,客户端在其中一个能访问数据库,另外一个不能访问
- win7频繁提示资源管理器已停止工作解决办法
- 博弈论总结
- C++四种常用的类型转换机制
- MTCNN--《Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks》疑问一大堆
- hdu--2005 第几天??
- jquery实现倒计时60秒发送邮件
- Android ContentProvider和Uri详解
- 简单的listview控件
- 【POJ 2387】Til the Cows Come Home(Dij最短路)
- PHP操作mongodb数据库操作类
- 判断是否为素数
- JQuery 常用命令总结
- 用rsync从Linux到Windows远程备份
- 闪频页面优化