您的位置:首页 > 其它

主席树

2015-06-06 19:06 309 查看

主席树

好神的数据结构,不过挺好写的。。

POJ 2104 K-th number

题目大意:
对一静态序列,每次询问[l,r]中第k大d

主席树模板题

贴代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#define M 100010
using namespace std;

struct Node{
int l,r,s;
}a[M*50];

int id[M],d[M],cnt,key;
void update(int l,int r,int &pos)
{
a[++cnt]=a[pos];
pos=cnt;
++a[pos].s;
if(l==r)
return ;
int m=(l+r)/2;
if(key<=m)
update(l,m,a[pos].l);
else
update(m+1,r,a[pos].r);
}

int query(int l,int r,int x,int y,int k)
{
if(l==r)
return l;
int mid=(l+r)/2,s=a[a[y].l].s-a[a[x].l].s;
if(k<=s)
return query(l,mid,a[x].l,a[y].l,k);
else
return query(mid+1,r,a[x].r,a[y].r,k-s);
}
bool cmp(int x,int y)
{
return d[x]<d[y];

}
int n,m;
int b[M];
int root[M];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&d[i]),id[i]=i;
sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;i++)
b[id[i]]=i;
for(int i=1;i<=n;i++)
{
root[i]=root[i-1];
key=b[i];
update(1,n,root[i]);
}
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&key);
int td=query(1,n,root[x-1],root[y],key);
printf("%d\n",d[id]);

}
return 0;
}


HDU 4417 Super Mario

题目大意:

对于一静态序列,询问[l,r]中小于x的个数

这题有树状数组解法,不过我用二分+主席树过了,
(跑得也很快,BIT 200+ms 二分+主席树 500+ms

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M  100010

using namespace std;

int d[M],b[M],id[M],root[M],cnt,key,T,n,m;
struct Node{

int l,r,s;
}a[M*30];

bool cmp (int x,int y)
{
return d[x]<d[y];
}
void update(int &t,int l,int r)
{
a[++cnt]=a[t];
t=cnt;
++a[t].s;
if(l==r)
return ;
int mid=(l+r)/2;
if(key<=mid)
update(a[t].l,l,mid);
else
update(a[t].r,mid+1,r);
}
int query(int l,int r,int x,int y,int k)
{
if(l==r)
return l;
int mid=(l+r)/2,s=a[a[y].l].s-a[a[x].l].s;
if(k<=s)
return query(l,mid,a[x].l,a[y].l,k);
else
return query(mid+1,r,a[x].r,a[y].r,k-s);
}

int main()
{
scanf("%d",&T);
for(int cas=1;cas<=T;cas++)
{
scanf("%d%d",&n,&m);
printf("Case %d:\n",cas);
for(int i=1;i<=n;i++)
scanf("%d",&d[i]),id[i]=i;
sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;i++)
b[id[i]]=i;
for(int i=1;i<=n;i++)
{
root[i]=root[i-1];
key=b[i];
update(root[i],1,n);
}
for(int i=1,x,y;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&key);
x++,y++;
if(d[id[query(1,n,root[x-1],root[y],y-x+1)]]<=key)
{
printf("%d\n",y-x+1);

}
else
if(d[id[query(1,n,root[x-1],root[y],1)]]>key)
{

printf("0\n");
}
else
{
int l=0,r=y-x+1;
int ans=0,mid;
while(l<=r)
{
int mid=(l+r)/2;
if(d[id[query(1,n,root[x-1],root[y],mid)]]<=key)
l=mid+1,ans=mid;
else
r=mid-1;
}
printf("%d\n",ans);
}
}
}
return 0;

}


SPOJ COT Count on a tree

s=s(lson[u])+s(lson[v])-2*s(lson[lca])

记住如果lca 在[l,mid] 中 s要+1

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define M 100005

using namespace std;

int g[M];
struct Edge
{
int nxt,v;
} e[M*2];

struct Node
{
int l,r,s;

} a[M*20];
vector<pair<int ,int > > q[M];
int cnt,num,key,n,m;
int p[M],fa[M],id[M],d[M],b[M],root[M];
int from[M],to[M],val[M];
void add(int u,int v)
{
e[++cnt].nxt=g[u],e[cnt].v=v,g[u]=cnt;
e[++cnt].nxt=g[v],e[cnt].v=u,g[v]=cnt;
}

void update(int &t,int l,int r)
{
a[++num]=a[t];
t=num;
++a[t].s;
if(l==r)
return ;
int mid=(l+r)/2;
if(key<=mid)
update(a[t].l,l,mid);
else
update(a[t].r,mid+1,r);
}

int ifind(int x)
{
return p[x] == x  ?  x : p[x]=ifind(p[x]);
}
bool vis[M];
int lca[M];

void dfs(int x)
{
// cout<<x<<endl;
p[x]=x;
key=b[x];
root[x]=root[fa[x]];
update(root[x],1,n);
for(int i=g[x]; i; i=e[i].nxt)
if(e[i].v!=fa[x])
{
//cout<<e[i].v<<endl;
fa[e[i].v]=x;
dfs(e[i].v);
p[e[i].v]=x;
}
vis[x]=1;
int t=q[x].size();
for(int i=0; i<t; ++i)
if(vis[q[x][i].first])
{
lca[q[x][i].second]=ifind(q[x][i].first);
}
}

bool cmp(int x,int y)
{
return d[x]<d[y];

}

int getans(int l,int r,int x,int y,int f,int k)
{
if(l==r)
return l;
int mid=(l+r)/2,s=a[a[x].l].s+a[a[y].l].s-(a[a[f].l].s<<1);
if(b[key]>=l && b[key]<=mid)
++s;
if(k<=s)
return getans(l,mid,a[x].l,a[y].l,a[f].l,k);
else
return getans(mid+1,r,a[x].r,a[y].r,a[f].r,k-s);
}

int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%d",&d[i]),id[i]=i;
sort(id+1,id+n+1,cmp);
for(int i=1; i<=n; i++)
b[id[i]]=i;
for(int i=1,x,y; i<n; i++)
{
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1; i<=m; ++i)
{
scanf("%d%d%d",&from[i],&to[i],&val[i]);
q[from[i]].push_back(pair<int, int> (to[i], i));
q[to[i]].push_back(pair<int, int> (from[i], i));
}
dfs(1);
for(int i=1; i<=m; ++i)
{
if(from[i]==to[i])
{
printf("%d\n", d[from[i]]);
continue;
}
key=lca[i];
printf("%d\n", d[id[getans(1, n, root[from[i]], root[to[i]], root[key], val[i])]]); //被root[ff]坑了一早上,写成了ff。唉
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: