主席树

单点修改

procedure makentree(l,r:longint);
  var
   mid,t:longint;
    begin
      inc(cnt);
      tr[cnt].z:=l;tr[cnt].y:=r;
      mid:=(l+r) div 2;
      t:=cnt;

      if l=r then exit;

      if l<=mid then
        begin
          tr[t].lc:=cnt+1;
          makentree(l,mid);
        end;
      if r>mid then
        begin
          tr[t].rc:=cnt+1;
          makentree(mid+1,r);
        end;
    end;

  procedure exptree(po,va:longint);
  var
   mid,t:longint;
    begin
      inc(cnt);
      tr[cnt].z:=tr[fol].z;
      tr[cnt].y:=tr[fol].y;
      tr[cnt].sum:=tr[fol].sum+1;
      mid:=(tr[fol].z+tr[fol].y) div 2;

      if tr[fol].z=tr[fol].y then exit;

      if va<=mid then
        begin
          tr[cnt].rc:=tr[fol].rc;
          tr[cnt].lc:=cnt+1;
          t:=fol;
          fol:=tr[fol].lc;
          exptree(tr[t].lc,va);
        end;
      if va>mid then
        begin
          tr[cnt].lc:=tr[fol].lc;
          tr[cnt].rc:=cnt+1;
          t:=fol;
          fol:=tr[fol].rc;
          exptree(tr[t].rc,va);
        end;
    end;

 cnt:=0;
    makentree(1,m);
    root[0]:=1;

    for i:=1 to n do
      begin
        root[i]:=cnt+1;
        fol:=root[i-1];
        exptree(fol,a[rk[i]]);
      end;
 

区间加减维护max,min(bzoj2653 middle)

#include<algorithm>
#include<cstdio>

 struct data{
     int key,num;
 }inp[200001];
 
 struct treenode{
     int l,r,lc,rc,mi,ma,toadd,ex;
 }tr[4000000];

int cnt,fol;
long long res[200001];
int a[200001],edi[200001],root[200001];
 
  int comp(const data &a,const data &b){
      if (a.key>b.key) return(0);
      if (a.key<b.key)return(1);
      if (a.num<b.num) return(1);
      return(0);
  }
  
  int ma(int a,int b){
      if (a>b) return(a);else return(b);
  }
  
  int mi(int a,int b){
    if (a<b) return(a);else return(b);
  }
  
  void makentree(int left,int right){
      tr[++cnt].l=left;tr[cnt].r=right;
      tr[cnt].toadd=0;
      tr[cnt].ex=0;
      int mid=(left+right)/2;
      if (left==right){
          tr[cnt].ma=left;tr[cnt].mi=left;return;
      }else {
          int t=cnt;
          tr[t].lc=cnt+1;
          makentree(left,mid);
          tr[t].rc=cnt+1;
          makentree(mid+1,right);
          tr[t].ma=ma(tr[tr[t].lc].ma,tr[tr[t].rc].ma);
          tr[t].mi=mi(tr[tr[t].lc].mi,tr[tr[t].rc].mi);
      }
  }
  
  void ex(int fol){
      tr[cnt+1]=tr[tr[fol].lc];
      tr[cnt+2]=tr[tr[fol].rc];
      tr[cnt+1].toadd+=tr[fol].toadd;
    tr[cnt+2].toadd+=tr[fol].toadd;
    tr[cnt+1].ex=1;
    tr[cnt+2].ex=1;
    tr[fol].ma+=tr[fol].toadd;
    tr[fol].mi+=tr[fol].toadd;
    tr[fol].toadd=0;
      tr[fol].lc=cnt+1;
      tr[fol].rc=cnt+2;
      cnt+=2;
      tr[fol].ex=0;
  }
  
  void exptree(int t,int left,int right){
         tr[t].ex=1;
         if (tr[t].l==left&&tr[t].r==right) 
         {tr[t].toadd-=2;
          return;}
         
       if (tr[t].ex) ex(t);
       int mid=(tr[fol].l+tr[fol].r)/2;
       int bckup=fol;
       if (left<=mid){fol=tr[fol].lc;exptree(tr[t].lc,left,mi(mid,right));}
       fol=bckup;
       if (right>mid){fol=tr[fol].rc;exptree(tr[t].rc,ma(left,mid+1),right);}
       tr[t].ma=ma(tr[tr[t].lc].ma+tr[tr[t].lc].toadd,tr[tr[t].rc].ma+tr[tr[t].rc].toadd);
       tr[t].mi=mi(tr[tr[t].lc].mi+tr[tr[t].lc].toadd,tr[tr[t].rc].mi+tr[tr[t].rc].toadd);
    }
        
  
  int getmax(int po,int l, int r){
        if (tr[po].l==l&&tr[po].r==r) return(tr[po].ma+tr[po].toadd);
        if (tr[po].ex) ex(po);
         
        int mid=(tr[po].l+tr[po].r)/2;
      int t=-1000000;
      if (l<=mid) t=ma(getmax(tr[po].lc,l,mi(r,mid)),t);
      if (r>mid)  t=ma(getmax(tr[po].rc,ma(mid+1,l),r),t);
      return(t);
  }
  
  int getmin(int po,int l,int r){
        if (tr[po].l==l&&tr[po].r==r) return(tr[po].mi+tr[po].toadd);
        if (tr[po].ex)ex(po);        
        int mid=(tr[po].l+tr[po].r)/2;
      int t=1000000;
      if (l==0){
          t=0;l++;
      }
      if (l<=mid) t=mi(getmin(tr[po].lc,l,mi(r,mid)),t);
      if (r>mid)  t=mi(getmin(tr[po].rc,ma(mid+1,l),r),t);
      return(t);
  }

  int main(){int n;
      scanf("%d",&n);
      
      for (int i=1;i<=n;i++){
          scanf("%lld",&inp[i].key);
          inp[i].num=i;
      }
      
    std::sort(inp+1,inp+n+1,comp);  
    
    for (int i=1;i<=n;i++){
        res[i]=inp[i].key;
        a[inp[i].num]=i;
        edi[i]=inp[i].num;
    }
    
    root[0]=1;
    makentree(1,n);
    

    for (int i=1;i<=n;i++){
        root[i]=++cnt;
        tr[root[i]]=tr[root[i-1]];
        fol=root[i-1];
        exptree(cnt,edi[i],n);    
    };
    
    int last=1;
    for (int i=1;i<=n;i++)
      if (res[i]==res[i-1])
        root[i-1]=root[i-2];
  ++cnt;
    int m;
    int tmp[5];
    scanf("%d",&m);
    long long lasans=0;
    for (int i=1;i<=m;i++){
      for (int j=1;j<=4;j++) {scanf("%d",&tmp[j]);  tmp[j]=((tmp[j]+lasans)%n+n)%n;};
        std::sort(tmp+1,tmp+5);
        int a=tmp[1]+1,b=tmp[2]+1,c=tmp[3]+1,d=tmp[4]+1;
        int l=1;int r=n;
        while (l<r){
            int mid=(l+r+1)/2;
            int t1=getmax(root[mid-1],c,d),
            t2=getmin(root[mid-1],a-1,b-1);
            if (t1-t2>=0) l=mid;
             else r=mid-1;
        }
        lasans=res[l];
        printf("%lld\n",lasans);
    }
    
    return(0);
  }
  
  

 ——————————————————————————————————————————————————

将l,r在递归时维护可以减少占用内存(BZOJ3524)

#include <cstdio>

  int cnt,r,l;
  int root[500001];

  struct data{
      int lc,rc,num;
  }tr[16666661];

  void build(int l,int r){
      ++cnt;
      if (l==r) return;
      
      int mid=(l+r)>>1,t=cnt;
      tr[t].lc=cnt+1;
      build(l,mid);
      tr[t].rc=cnt+1;
      build(mid+1,r);
  }
  
  void edi(int po,int trpol,int trpor,int tar){
      tr[++cnt]=tr[po];
      tr[cnt].num++;
      if (trpol==trpor) return;
      
      int mid=(trpol+trpor)>>1;
      if (tar<=mid){
        tr[cnt].lc=cnt+1;
      edi(tr[po].lc,trpol,mid,tar);    
    }else{
      tr[cnt].rc=cnt+1;
      edi(tr[po].rc,mid+1,trpor,tar);
    }
  } 
  
  int query(int poa,int pob,int trpol,int trpor,int k){
      if (trpol==trpor){
        int tmp=tr[poa].num-tr[pob].num;
      if (tmp>(r-l+1)/2) return(trpol);else return(0);
    }
        
      int lcnum=tr[tr[poa].lc].num-tr[tr[pob].lc].num,mid=(trpol+trpor)>>1;
    if (lcnum>=k) return(query(tr[poa].lc,tr[pob].lc,trpol,mid,k));
                  return(query(tr[poa].rc,tr[pob].rc,mid+1,trpor,k-lcnum));  
  }

  int main(){      
      int n,m;
      scanf("%d%d",&n,&m);
      root[0]=1;
      build(1,n);  
    for (int i=1;i<=n;i++){
      int t;
      scanf("%d",&t);
      root[i]=cnt+1;
      edi(root[i-1],1,n,t);    
    }    
    
    for (int i=1;i<=m;i++){
      scanf("%d%d",&l,&r);
      int ret=query(root[r],root[l-1],1,n,(r-l+2)/2);
      printf("%d\n",ret);    
    }
  }

 

posted @ 2016-04-13 17:04  z1j1n1  阅读(185)  评论(0编辑  收藏  举报