【poj1901-求區間第k大值(帶修改)】樹狀數組套主席樹


901: Zju2112 Dynamic Rankings

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 7025  Solved: 2925
[Submit][Status][Discuss]

Description

給定一個含有n個數的序列a[1],a[2],a[3]……a[n],程序必須回答這樣的詢問:對於給定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的數是多少(1≤k≤j-i+1),並且,你可以改變一些a[i]的值,改變后,程序還能針對改變后的a繼續回答上面的問題。你需要編一個這樣的程序,從輸入文件中讀入序列a,然后讀入一系列的指令,包括詢問指令和修改指令。對於每一個詢問指令,你必須輸出正確的回答。 第一行有兩個正整數n(1≤n≤10000),m(1≤m≤10000)。分別表示序列的長度和指令的個數。第二行有n個數,表示a[1],a[2]……a[n],這些數都小於10^9。接下來的m行描述每條指令,每行的格式是下面兩種格式中的一種。 Q i j k 或者 C i t Q i j k (i,j,k是數字,1≤i≤j≤n, 1≤k≤j-i+1)表示詢問指令,詢問a[i],a[i+1]……a[j]中第k小的數。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改變成為t。

Input

對於每一次詢問,你都需要輸出他的答案,每一個輸出占單獨的一行。

Output

 

Sample Input

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

Sample Output

3
6

HINT

 

20%的數據中,m,n≤100; 40%的數據中,m,n≤1000; 100%的數據中,m,n≤10000。

 

-------------------------------------------------------------------------------------

嗷嗷嗷A了好海森

首先要回憶一下樹狀數組的樣子。。它是一棵樹的結構,也就是一個點只會被另一個點所訪問到(父親只有一個)。

上一題不帶修改的主席樹中,每一棵樹是維護前綴區間1~L的。

這樣,要是我們要修改一個數的話,就要把后面的主席樹全部修改了。。復雜度變成了m*n*logn,這是不能接受的。

然后大神們就想到了樹狀數組!

我們修改每一棵主席樹維護的區間,對於第i棵主席樹,維護樹狀數組中所對應的lowbit(i)個數。

然后修改就只需要m*logn*logn了。

查詢則變成了logn*logn的了。

 

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;  8 
 9 const int N=10010,INF=(int)1e9+100;  10 int n,m,pl,tl,mx;  11 int a[2*N],num[2*N],crt[2*N],root[2*N];  12 char s[10];  13 struct trnode{  14     int lc,rc,cnt;  15 }t[300*N];  16 struct ques{  17     int l,r,k,x,d;  18     bool tmp;  19 }q[N];  20 struct node{  21     int d,id;  22 }p[2*N];  23 
 24 bool cmp(node x,node y){return x.d<y.d;}  25 
 26 int bt(int l,int r)  27 {  28     int x=++tl;  29     t[x].cnt=0;  30     t[x].lc=t[x].rc=0;  31     if(l<r)  32  {  33         int mid=(l+r)/2;  34         t[x].lc=bt(l,mid);  35         t[x].rc=bt(mid+1,r);  36  }  37     return x;  38 }  39 
 40 int update(int rt,int p,int d)  41 {  42     int now=++tl,tmp=now;  43     int l=1,r=mx,mid;  44     t[now].cnt=t[rt].cnt+d;  45     while(l<r)  46  {  47         mid=(l+r)/2;  48         if(p<=mid)  49  {  50             r=mid;  51             t[now].lc=++tl;  52             t[now].rc=t[rt].rc;  53             rt=t[rt].lc;  54             now=tl;  55  }  56         else 
 57  {  58             l=mid+1;  59             t[now].lc=t[rt].lc;  60             t[now].rc=++tl;  61             rt=t[rt].rc;  62             now=tl;  63  }  64         t[now].cnt=t[rt].cnt+d;  65  }  66     return tmp;  67 }  68 
 69 void add(int x,int p,int d)  70 {  71     for(int i=x;i<=n;i+=(i&(-i))) root[i]=update(root[i],p,d);  72 }  73 
 74 int getsum(int x)  75 {  76     int ans=0;  77     for(int i=x;i>=1;i-=(i&(-i))) ans+=t[t[crt[i]].lc].cnt;  78     return ans;  79 }  80 
 81 int query(int lx,int rx,int k)  82 {  83     for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=root[i];//多棵樹同時走。
 84     for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=root[i];  85     int l=1,r=mx,mid,sum;  86     while(l<r)  87  {  88         mid=(l+r)/2;  89         sum=getsum(rx)-getsum(lx-1);  90         if(sum>=k)  91  {  92             r=mid;  93             for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].lc;  94             for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].lc;  95  }  96         else
 97  {  98             l=mid+1;  99             k-=sum; 100             for(int i=lx-1;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].rc; 101             for(int i=rx;i>=1;i-=(i&(-i))) crt[i]=t[crt[i]].rc; 102  } 103  } 104     return l; 105 } 106 
107 int main() 108 { 109     freopen("a.in","r",stdin); 110     scanf("%d%d",&n,&m); 111     pl=n;tl=0; 112     for(int i=1;i<=n;i++) 113  { 114         scanf("%d",&a[i]); 115         p[i].d=a[i];p[i].id=i; 116  } 117     for(int i=1;i<=m;i++) 118  { 119         scanf("%s",s); 120         if(s[0]=='Q') 121  { 122             q[i].tmp=0; 123             scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k); 124  } 125         else 
126  { 127             q[i].tmp=1; 128             scanf("%d%d",&q[i].x,&q[i].d); 129             p[++pl].d=q[i].d;p[pl].id=n+i; 130  } 131  } 132     sort(p+1,p+1+pl,cmp); 133     mx=0;p[0].d=INF; 134     for(int i=1;i<=pl;i++) 135  { 136         if(p[i].d!=p[i-1].d) mx++,num[mx]=p[i].d; 137         if(p[i].id<=n) a[p[i].id]=mx; 138         else q[p[i].id-n].d=mx; 139  } 140     // for(int i=1;i<=n;i++) printf("%d ",a[i]);printf("\n");
141     root[0]=bt(1,mx); 142     for(int i=1;i<=n;i++) 143         root[i]=root[0]; 144     for(int i=1;i<=n;i++) 145         add(i,a[i],1); 146     for(int i=1;i<=m;i++) 147  { 148         if(q[i].tmp==0) 149             printf("%d\n",num[query(q[i].l,q[i].r,q[i].k)]); 150         else
151  { 152             add(q[i].x,a[q[i].x],-1); 153             add(q[i].x,q[i].d,1); 154             a[q[i].x]=q[i].d;//debug
155  } 156  } 157     return 0; 158 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM