您的位置:首页 > 其它

poj 2104 分类: poj 2015-02-09 23:23 91人阅读 评论(0) 收藏

2015-02-09 23:23 429 查看
poj2104

今天研究了一下函数式线段树(主席树),感觉很厉害呀!

主席树,其意义是对每序列中每个元素都建一棵子树,来描述前i个元素的信息

直接建树的话,时间、空间都是N∗N∗logN ,肯定会MLE/TLE

记Tree(i)为描述1~i的线段树

Tree(i)与Tree(i−1)会有很多公共的信息,所以只有logN条新增信息

所以建树Tree(i)时,可以和Tree(i−1)共用一些节点,其余只需新增logN个节点

初始化Tree(0):建一棵空树

时间复杂度O(N∗logN)

空间复杂度O(N∗logN)

主席树空间计算:SIZE=N∗logN+3∗N


具体参见fhq神犇的:《范浩强_wc2012谈谈各种数据结构》



对于这个题,我除了写主席树就没动什么脑子,线段树代码直接敲,有些乱搞倾向。。。

tree(i)描述整个序列中 1~i小的元素在树中的分布情况

然后二分答案,l和r,满足 count[i,j,tree(l)]<k<=count[i,j,tree(r)]

最后结果:ans=value(r) ,其实还是写长了。。。

时间复杂度(N∗logN+M∗logN)


较简易的代码实现: http://blog.csdn.net/q775968375 Orz



UPD:^_^,然而,最后我发现,我的主席树映射写反了233333,难怪代码这么长。。。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<math.h>
#define SIZE 2000000
#define MAXN 100005

int n,m;
struct node{int l,r,c[2],cnt;}mp[SIZE]={0};
int ml=0,root[MAXN]={0};
int a[MAXN]={0},rank[MAXN]={0},v[MAXN]={0},swap;
int ll,rr,ki;

int buildtree0(int l0,int r0)
{
int ret=++ml,mid=(l0+r0)>>1;

mp[ret].l=l0,mp[ret].r=r0;

if(l0==r0)return ret;

if(l0<=mid)  mp[ret].c[0]=buildtree0(l0,mid);
if(mid+1<=r0)mp[ret].c[1]=buildtree0(mid+1,r0);

return ret;
}

int buildtree(int rt,int xi)
{
int mid=(mp[rt].l+mp[rt].r)>>1;
int ret=++ml,tag;

mp[ret].l=mp[rt].l;
mp[ret].r=mp[rt].r;

if(mp[rt].l==mp[rt].r)
{
mp[ret].c[0]=mp[ret].c[1]=0;
mp[ret].cnt=1;

return ret;
}

/*
if(xi<=mid)
{
mp[ret].c[0]=buildtree(mp[rt].c[0],xi);
mp[ret].c[1]=mp[rt].c[1];
}
else
{
mp[ret].c[0]=mp[rt].c[0];
mp[ret].c[1]=buildtree(mp[rt].c[1],xi);
}
*/
tag=(xi<=mid);

mp[ret].c[tag]=mp[rt].c[tag];
mp[ret].c[tag^1]=buildtree(mp[rt].c[tag^1],xi);

mp[ret].cnt=mp[mp[ret].c[0]].cnt+mp[mp[ret].c[1]].cnt;
return ret;
}

void sort(int l,int r)
{
int i=l,j=r;
int t=a[rank[l+rand()%(r-l+1)]];

while(i<=j)
{
while(a[rank[i]]<t)i++;
while(a[rank[j]]>t)j--;

if(i<=j)
{
swap=rank[i];
rank[i]=rank[j];
rank[j]=swap;
i++,j--;
}
}

if(l<j)sort(l,j);
if(i<r)sort(i,r);
}

int count(int s,int l,int r)
{
int mid=(mp[s].l+mp[s].r)>>1;

if(mp[s].l==l && mp[s].r==r)return mp[s].cnt;

if(r<=mid)
{
return count(mp[s].c[0],l,r);
}
else if(l>=mid+1)
{
return count(mp[s].c[1],l,r);
}
else
{
return count(mp[s].c[0],l,mid)+count(mp[s].c[1],mid+1,r);
}

}
int getnum();
int main()
{
int i,l,r,mid;

#ifndef ONLINE_JUDGE
freopen("poj2104.in","r",stdin);
freopen("poj2104.out","w",stdout);
#endif

srand(time(NULL));

n=getnum();m=getnum();

for(i=1;i<=n;i++)
rank[i]=i,a[i]=getnum();

if(n!=1)sort(1,n);

for(i=1;i<=n;i++)
{
v[rank[i]]=i;
}

root[0]=buildtree0(1,n);
for(i=1;i<=n;i++)
{
root[i]=buildtree(root[i-1],rank[i]);
}

while(m--)
{
ll=getnum();
rr=getnum();
ki=getnum();

l=1;r=n;
if(count(root[l],ll,rr)>=ki)
printf("%d\n",a[rank[l]]);
else
{
while(l+1!=r)
{
mid=(l+r)>>1;

if(count(root[mid],ll,rr)>=ki)
r=mid;
else
l=mid;
}
printf("%d\n",a[rank[r]]);
}
}

#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}

char str[20],sl;int gi,gret,cq;
int getnum()
{
gret=0;

scanf("%s",str);
sl=strlen(str);

if(str[0]=='-')cq=-1,gi=1;
else           cq=1,gi=0;

for(;gi<sl;gi++)
{
gret*=10;
gret+=str[gi]-'0';
}

return gret*cq;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐