您的位置:首页 > 其它

HDU 4605 Magic Ball Game 树上主席树

2015-04-10 10:50 302 查看
用两颗主席树分别存大小为p的球的个数,还有就是处于右儿子的大小为p的个数即可,然后就是简单主席树。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=100005;
struct pi{
int lson;
int rson;
int sum;
}pp[maxn*18*2];
int root[2][maxn],tot,a[maxn],b[maxn],pa[maxn];
int ll[maxn],rr[maxn];
void build(int cnt,int l,int r){
pp[cnt].sum=0;
if(l==r) return ;
int mid=(l+r)/2;
pp[cnt].lson=tot+1;
tot++;
build(tot,l,mid);
pp[cnt].rson=tot+1;
tot++;
build(tot,mid+1,r);
}
void merg(int qq,int cnt,int n,int p,int k){
int le=1,ri=n,mid;
while(le<=ri){
pp[cnt]=pp[qq];
mid=(le+ri)/2;
pp[cnt].sum+=k;
if(le==ri) return ;
if(p<=mid){
pp[cnt].lson=tot+1;
tot++;
cnt=tot;
qq=pp[qq].lson;
ri=mid;
}
else{
pp[cnt].rson=tot+1;
tot++;
cnt=tot;
qq=pp[qq].rson;
le=mid+1;
}
}
}
int query(int cnt,int le,int ri,int l,int r){
if(le>=l&&ri<=r){
return pp[cnt].sum;
}
int s=0;
int mid=(le+ri)/2;
if(l<=mid) s+=query(pp[cnt].lson,le,mid,l,r);
if(r>mid) s+=query(pp[cnt].rson,mid+1,ri,l,r);
return s;
}
void dfs(int u,int n){
if(ll[u]==-1) return ;
root[0][ll[u]]=tot+1;
tot++;
merg(root[0][u],tot,n,a[ll[u]],1);
root[0][rr[u]]=tot+1;
tot++;
merg(root[0][u],tot,n,a[rr[u]],1);
root[1][ll[u]]=tot+1;
tot++;
merg(root[1][u],tot,n,a[ll[u]],0);
root[1][rr[u]]=tot+1;
tot++;
merg(root[1][u],tot,n,a[u],1);
dfs(ll[u],n);
dfs(rr[u],n);
}
int main()
{
int i,n,m,t;
cin>>t;
while(t--){
cin>>n;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
for(i=1;i<=n;i++){
a[i]=(int)(lower_bound(b+1,b+1+n,a[i])-b);
}
memset(ll,-1,sizeof(ll));
memset(rr,-1,sizeof(rr));
cin>>m;
pa[1]=0;
for(i=0;i<m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
pa[b]=pa[c]=a;
ll[a]=b;
rr[a]=c;
}
tot=0;
root[0][0]=tot;
build(tot,1,n);
root[1][0]=tot+1;
tot++;
build(tot,1,n);
root[0][1]=tot+1;
tot++;
merg(root[0][0],root[0][1],n,a[1],1);
root[1][1]=tot+1;
tot++;
merg(root[1][0],root[1][1],n,a[1],0);
dfs(1,n);
cin>>m;
for(i=0;i<m;i++){
int a,bb;
scanf("%d%d",&a,&bb);
int p=lower_bound(b+1,b+1+n, bb)-b;
if(p<=n&&b[p]==bb){
if(query(root[0][pa[a]],1,n,p,p)){
printf("0\n");
continue;
}
}
int s=0,s1=0;
if(p>1){
s+=3*query(root[0][pa[a]],1,n,1,p-1);
s1+=query(root[1][a],1,n,1,p-1);
}
if(p<=n&&b[p]==bb){
if(p<n)
s+=query(root[0][pa[a]],1,n,p+1,n);
}
else{
if(p<=n){
s+=query(root[0][pa[a]],1,n,p,n);
}
}
printf("%d %d\n",s1,s);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: