主席树
好神的数据结构,不过挺好写的。。
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[td]]);
}
return 0;
}
题目大意:
对于一静态序列,询问[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