【樹套樹】【樹狀數組套主席樹】

來源:互聯網
上載者:User

標籤: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 }

 

【樹套樹】【樹狀數組套主席樹】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.