【主席树】【bzoj2161】[hdu4348]

时间:2023-03-09 07:49:12
【主席树】【bzoj2161】[hdu4348]
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 400000
using namespace std;
];
],cnt,n,m,x,y,k,rson[],sum[];
bool cmp(node a,node b)
{
  return a.x<b.x;
}
void update(int st,int ed,int x,int &y,int v)
{
  //printf("%d %d %d %d\n",st,ed,x,y);
  ;y=++cnt;sum[y]=sum[x]+;
  if(st==ed)return;
  lson[y]=lson[x];rson[y]=rson[x];
  if(v<=mid)
  {
    update(st,mid,lson[x],lson[y],v);
  }else
  {
    update(mid+,ed,rson[x],rson[y],v);
  }
}
int query(int x,int y,int rk)
{
  ,r=n,a=root[x-],b=root[y];
  while(l<r)
  {
    ;
    int tmp=sum[lson[b]]-sum[lson[a]];
    if(tmp>=rk)r=mid,a=lson[a],b=lson[b];
    ,a=rson[a],b=rson[b];
  }
  return l;
}
int main()
{
  scanf("%d%d",&n,&m);
  ;i<=n;i++)scanf("%d",&a[i]),b[i].x=a[i],b[i].h=i;
  sort(b+,b+n+,cmp);].x,rank=;
  ;i<=n;i++)if(b[i].x==now)a[b[i].h]=rank;else
  now=b[i].x,rank++,a[b[i].h]=rank;
  memset(root,,sizeof(root));
  ;i<=n;i++)
  {
    update(,n,root[i-],root[i],a[i]);
  }
  ;i<=m;i++)
  {
    scanf("%d%d%d",&x,&y,&k);
    int last=query(x,y,k);printf("%d\n",last);
  }
}

以上是罗oj的模板题,这里输出的答案没有离散回去还有点问题。。先不要交到poj上

下面可以先尝试着用主席树写一下[bzoj2161]。。。虽然ppt的题解上是扔到平衡树里搞?

暑期主席树小专题

要做的事情多着呢。

A:也是一个模(mu)板题,不多说。

B:count on a tree,强制在线,以前就做过了。这里感觉只有query()需要注意一下的。

#include<cstdio>
#include<algorithm>
#define M 2000005
#define N 200005
using namespace std;
int n,m,cnt,size,tot,last,k,edgenum;
],num[N],pos[N],hash[N],root[N],ls[M],rs[M],sum[M],deep[N],head[N],vet[N],next[N],fa[N][];
];
bool cmp(node a,node b)
{
    return a.x<b.x;
}
void add(int u,int v)
{
    edgenum++;vet[edgenum]=v;next[edgenum]=head[u];head[u]=edgenum;
}
void update(int st,int ed,int x,int &y,int nb)
{
    //printf("%d %d %d %d\n",st,ed,x,y);
    y=++size;sum[y]=sum[x]+;if(st==ed)return;
    ls[y]=ls[x];rs[y]=rs[x];
    ;
    if(nb<=mid)update(st,mid,ls[x],ls[y],nb);
    ,ed,rs[x],rs[y],nb);
}
int lca(int x,int y)
{
    if(deep[x]<deep[y])swap(x,y);
    int t=deep[x]-deep[y];
    ;i<=;i++)<<i)&t)x=fa[x][i];
    ;i>=;i--)if(fa[x][i]!=fa[y][i])
     x=fa[x][i],y=fa[y][i];
    ];
}
int query(int x,int y,int rk)
{
    ];
    a=root[pos[a]],b=root[pos[b]],c=root[pos[c]],d=root[pos[d]];
    ,r=tot;
    while(l<r)
    {
        ;
        int tmp=sum[ls[a]]+sum[ls[b]]-sum[ls[c]]-sum[ls[d]];
        if(tmp>=rk)r=mid,a=ls[a],b=ls[b],c=ls[c],d=ls[d];
        ,a=rs[a],b=rs[b],c=rs[c],d=rs[d];
    }
    return hash[l];
}
void dfs(int u)
{
    num[++cnt]=u,pos[u]=cnt;
    ;i<=;i++)
     <<i)<=deep[u])fa[u][i]=fa[fa[u][i-]][i-];
     else break;
    int e=head[u];
    )
    {
        int v=vet[e];
        ])
        {
            deep[v]=deep[u]+;
            fa[v][]=u;dfs(v);
        }
        e=next[e];
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    ;i<=n;i++)scanf("%d",&a[i]),bx[i].x=a[i],bx[i].h=i;
    sort(bx+,bx+n+,cmp);
    ,now=bx[].x;tot++;hash[tot]=now;
    ;i<=n;i++)
    {
        if(bx[i].x==now)a[bx[i].h]=rank;
        else
        {
            rank++;now=bx[i].x;a[bx[i].h]=rank;
            tot++;hash[tot]=now;
        }
    }
    int x,y;
    ;i<=n-;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    cnt=;dfs();
    ;i<=n;i++)
    {
        int t=num[i];
        update(,tot,root[pos[fa[t][]]],root[i],a[t]);
    }
    ;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&k);
        x=x^last;last=query(x,y,k);
        printf("%d",last);if(i!=m)printf("\n");
    }
}

bzoj2588

C:count on a treeⅡ,八中oj上面基本上都被卡了,又没有很多std供我在hdu上测试。。。就算啦(懒人就是这样,AC无望的题连学都不想学惹

E:也蛮简单的,然而写了一下午。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 400000
using namespace std;
;
],root[N],rson[],sum[];
],back[];
struct node{
  int x,h;
}b[];
bool cmp(node a,node b)
{
  return a.x<b.x;
}
void update(int st,int ed,int x,int &y,int v)
{
   ;y=++cnt;sum[y]=sum[x]+;
   if(st==ed)return;
   lson[y]=lson[x];rson[y]=rson[x];
   if(v<=mid)update(st,mid,lson[x],lson[y],v);
    ,ed,rson[x],rson[y],v);

}
int query(int x,int y,int kth)
{
  ,r=n,a=root[x-],b=root[y],tmp=;
  while(l<=r)
  {
    if(l==r){
      if(back[l]<=kth)tmp+=sum[lson[b]]-sum[lson[a]];
      return tmp;
    }
    ;int x=sum[lson[b]]-sum[lson[a]];
    ,tmp+=x,a=rson[a],b=rson[b];
     else r=mid,a=lson[a],b=lson[b];
    //printf("====%d %d %d %d %d\n",l,r,mid,x,tmp);
  }
  return tmp;
}
int main()
{
scanf("%d",&cases);
;cas<=cases;cas++)
{
  scanf(;
  memset(sum,,sizeof(sum));
  memset(root,,sizeof(root));
  memset(lson,,sizeof(lson));
  memset(rson,,sizeof(rson));
  ;i<=n;i++)
  {
    scanf("%d",&a[i]);b[i].x=a[i];b[i].h=i;
  }
  ;i<=n;i++)back[i]=;
  sort(b+,b+n+,cmp);
  ].x,rank=;back[rank]=now;
  ;i<=n;i++)
   if(b[i].x==now)a[b[i].h]=rank;
    else now=b[i].x,rank++,back[rank]=b[i].x,a[b[i].h]=rank;
  ;i<=n;i++)update(,n,root[i-],root[i],a[i]);
  printf("Case %d:\n",cas);
  ;i<=m;i++)
  {
    int L,R,H;
    scanf("%d%d%d",&L,&R,&H);L++;R++;
    printf("%d\n",query(L,R,H));
  }
}
}  

hdu4417 Super Mario

[bzoj2161]布娃娃

QAQ不造为啥这道题做的人这么少。。。是因为太水?还是因为雨荨萌萌的题面?。。。。

我不管,除了读入略坑以外,其它的看起来还是很可做的嘛。

把每一条线段看作插入与删除两个操作,对于它们的耐心值P【i】,(我这里看不到完整的题面,但是从一些std可以看出j喜欢i,当且仅当i被j的线段包围了)

那么思路就来了,把魅力值离散一下,add操作与query操作套一套就可以了。

而且这里也不需要什么继承,一棵root搞定。yep

#include<cstdio>
#include<algorithm>
#define mo 19921228
#define ll long long
#define N 100005
using namespace std;
,n,qn,root=;
],rson[],sum[],back[N];
struct node{
  int x,h;
}dat[N];
struct wxx{
  int c,k,x,f;
}q[];
bool cmp1(node a,node b)
{
  return a.x<b.x;
}
bool cmp2(wxx a,wxx b)
{
  if(a.x==b.x)return a.f<b.f;
  return a.x<b.x;
}
void work()
{
  int add,fir,mdd,prod;
  scanf("%d%d%d%d",&add,&fir,&mdd,&prod);
  ]=x;
  ;i<=n;i++)
   a[i]=(1ll*a[i-]*prod+add+i)%mdd;
}
void add(int &x,int l,int r,int v,int val)
{
  )x=++cnt;sum[x]+=val;//printf("%d %d\n",l,r);
  if(l==r)return;
  ;
  ,r,v,val);
}
int query(int x,int l,int r,int kth)
{
  //printf("%d %d\n",l,r);
  if(l==r)return l;
  //printf("%d %d\n",l,r);
  ;
  ,r,kth);
   else return query(lson[x],l,mid,kth-sum[rson[x]]);
}
int main()
{
  scanf("%d",&n);
  work();;i<=n;i++)P[i]=a[i];
  work();;i<=n;i++)C[i]=a[i];
  work();;i<=n;i++)L[i]=a[i];
  work();;i<=n;i++)R[i]=a[i];
  //for(int i=1;i<=n;i++)printf("%d ",C[i]);printf("\n");
  ;i<=n;i++)dat[i].x=C[i],dat[i].h=i;
  sort(dat+,dat+n+,cmp1);
  ].x,rank=;back[]=now;
  ;i<=n;i++)
   if(dat[i].x==now)C[dat[i].h]=rank;else now=dat[i].x,rank++,back[rank]=now,C[dat[i].h]=rank;
  //for(int i=1;i<=n;i++)printf("%d ",C[i]);  printf("\n");
  ;i<=n;i++)
  {
    if(L[i]>R[i])swap(L[i],R[i]);
    qn++;q[qn].f=;  q[qn].x=L[i];    q[qn].c=C[i];
    qn++;q[qn].f=;  q[qn].x=P[i];    q[qn].c=;   q[qn].k=i;
    qn++;q[qn].f=-; q[qn].x=R[i]+;  q[qn].c=C[i];
  }
  sort(q+,q+qn+,cmp2);
  //for(int i=1;i<=qn;i++)printf("%d %d %d\n",q[i].x,q[i].f,q[i].c);
  ll ans=;
  ;i<=qn;i++)
  {
    )add(root,,n,q[i].c,);
     )add(root,,n,q[i].c,-);
    else if(sum[root]>=q[i].k)
     ans=(ans+back[query(root,,n,q[i].k)])%mo;
  }
  printf("%lld\n",ans);
} 

bzoj2161