主席树
单点修改
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); } }