標籤:while sort names 涵蓋 line getch 首碼和 16px work
這是你顧第一次寫【樹套樹】!!!!!!!!
【原題】
求區間第k小元素,區間可修改
【正解】
如果沒有修改的話,就直接寫搞個主席樹利用首碼和加加減減一下就好了。但是多了個修改,修改以為著從當前修改節點k到往後n-k個樹頂所代表的樹全部都要修改,這是一件非常操蛋的事情。回想起多年前學資料結構初步的時候,區間批量修改無非就是樹狀數組or線段樹。故我們借用樹狀數組的輪廓來構建主席樹的各樹頂。
對樹狀數組每個節點,我們都當成是主席樹的樹頂,改樹頂所涵蓋的區間與樹狀數組該節點意義相同。
【查詢】查詢區間[l,r],先求出區間[1,l-1],再求出[1,r],至於求法嘛就跟樹狀數組那個lowbit一樣,每次lowbit lowbit減下去就行了。
【修改】修改一個節點後,類於樹狀數組,將往後logn個節點都給改了就行。over
1 //copy by @ljq-despair 2 #include<bits/stdc++.h> 3 using namespace std; 4 inline int gi(){ 5 char a=getchar();int b=0; 6 while(a<‘0‘||a>‘9‘)a=getchar(); 7 while(a>=‘0‘&&a<=‘9‘)b=b*10+a-‘0‘,a=getchar(); 8 return b; 9 }10 const int N=1e4+50;11 struct node {int l,r,x;} t[N*900];12 struct ppp {int l,r,op,k;} b[N];13 int cmp(int* x,int* y) {return *x<*y;}14 int a[N],p[N*5],n,m,tot1,tot2,lshh,cnt=1,root[N],root1[N],q1[N],q2[N]; int *lsh[N*5];15 void work(){16 sort(lsh+1,lsh+lshh+1,cmp);p[0]=-1;17 for(int i=1,j=0;i<=lshh;++i)18 {19 if(*lsh[i]!=p[j])p[++j]=*lsh[i];20 *lsh[i]=j;21 }22 }23 int modify(int l,int r,int x,int k,int o){24 int y=++cnt;25 t[y]=t[x];t[y].x+=o;26 if(l==r)return y;27 int mid=(l+r)>>1;28 if(k<=mid)t[y].l=modify(l,mid,t[x].l,k,o);29 else t[y].r=modify(mid+1,r,t[x].r,k,o);30 return y;31 }32 int query(int l,int r,int s1,int s2,int k){33 if(l==r)return l;34 int x=t[t[s2].l].x-t[t[s1].l].x;35 for(int i=1;i<=tot1;++i)x-=t[t[q1[i]].l].x;36 for(int i=1;i<=tot2;++i)x+=t[t[q2[i]].l].x;37 int mid=(l+r)>>1;38 if(x>=k)39 {40 for(int i=1;i<=tot1;++i)q1[i]=t[q1[i]].l;41 for(int i=1;i<=tot2;++i)q2[i]=t[q2[i]].l;42 return query(l,mid,t[s1].l,t[s2].l,k);43 }44 else45 {46 for(int i=1;i<=tot1;++i)q1[i]=t[q1[i]].r;47 for(int i=1;i<=tot2;++i)q2[i]=t[q2[i]].r;48 return query(mid+1,r,t[s1].r,t[s2].r,k-x);49 }50 }51 int main(){52 cin>>n>>m;53 for(int i=1;i<=n;++i)54 {55 a[i]=gi();56 lsh[++lshh]=&a[i];57 }58 for(int i=1;i<=m;++i)59 {60 char aa=getchar();61 while(!(aa==‘Q‘||aa==‘C‘))aa=getchar();62 b[i].l=gi();63 b[i].r=gi();64 if(aa==‘C‘)65 {66 b[i].op=1;67 lsh[++lshh]=&b[i].r;68 }69 else b[i].k=gi();70 }71 work();72 for(int i=1;i<=n;++i)73 root1[i]=root[1];74 for(int i=1;i<=n;++i)75 root[i]=modify(1,lshh,root[i-1],a[i],1);76 for(int i=1;i<=m;++i)77 if(b[i].op)78 {79 int x=b[i].l,y=b[i].r,s=a[x];a[x]=y;80 while(x<=n)81 {82 root1[x]=modify(1,lshh,root1[x],s,-1);83 root1[x]=modify(1,lshh,root1[x],y,1);84 x+=(x&(-x));85 }86 }87 else88 {89 tot1=0,tot2=0;int x=b[i].l-1;90 while(x){q1[++tot1]=root1[x];x-=(x&(-x));}x=b[i].r;91 while(x){q2[++tot2]=root1[x];x-=(x&(-x));}92 printf("%d\n",p[query(1,lshh,root[b[i].l-1],root[b[i].r],b[i].k)]);93 }94 return 0;95 }
【樹套樹】【樹狀數組套主席樹】