BZOJ 1901 树状数组+函数式线段树

题解:

带单点更新的区间第k大~

函数式线段树秒杀了~

与不带修改的函数式线段树唯一不同的在于线段树中的每个结点维护的都是这个位置的结点的树状数组值~

然后自己随便怎么胡搞啊神马的就nlog^2n了~

 

View Code
  1 #include <iostream>

  2 #include <cstdlib>

  3 #include <cstdio>

  4 #include <cstring>

  5 #include <algorithm>

  6 

  7 #define N 110040

  8 #define lowbit(x) x&-x

  9 

 10 using namespace std;

 11 

 12 int h[N],ls[N<<5],rs[N<<5],sum[N<<5];

 13 int cnt,n,m,gs,num;

 14 int a[N],bh[N];

 15 int dat[N][4],ln[N],rn[N],lc,rc;

 16 

 17 inline int newnode(int s,int l,int r)

 18 {

 19     ++cnt; sum[cnt]=s; ls[cnt]=l; rs[cnt]=r;

 20     return cnt;

 21 }

 22 

 23 inline void build(int l,int r,int &rt)

 24 {

 25     rt=newnode(0,0,0);

 26     if(l==r) return;

 27     int mid=(l+r)>>1;

 28     build(l,mid,ls[rt]);

 29     build(mid+1,r,rs[rt]);

 30 }

 31 

 32 inline void updata(int last,int pos,int val,int l,int r,int &rt)

 33 {

 34     rt=newnode(sum[last]+val,ls[last],rs[last]);

 35     if(l==r) return;

 36     int mid=(l+r)>>1;

 37     if(pos<=mid) updata(ls[last],pos,val,l,mid,ls[rt]);

 38     else updata(rs[last],pos,val,mid+1,r,rs[rt]);

 39 }

 40 

 41 inline void modify(int x,int pos,int val)

 42 {

 43     int tmp;

 44     while(x<=n)

 45     {

 46         updata(h[x],pos,val,1,num,tmp);

 47         h[x]=tmp;

 48         x+=lowbit(x);

 49     }

 50 }

 51 

 52 inline int query(int l,int r,int k)

 53 {

 54     if(l==r) return l;

 55     int tr=0,tl=0;

 56     for(int i=1;i<=rc;i++) tr+=sum[ls[rn[i]]];

 57     for(int i=1;i<=lc;i++) tl+=sum[ls[ln[i]]];

 58     tr-=tl;

 59     int mid=(l+r)>>1;

 60     if(k<=tr)

 61     {

 62         for(int i=1;i<=rc;i++) rn[i]=ls[rn[i]];

 63         for(int i=1;i<=lc;i++) ln[i]=ls[ln[i]];

 64         return query(l,mid,k);

 65     }

 66     else

 67     {

 68         for(int i=1;i<=rc;i++) rn[i]=rs[rn[i]];

 69         for(int i=1;i<=lc;i++) ln[i]=rs[ln[i]];

 70         return query(mid+1,r,k-tr);

 71     }

 72 }

 73 

 74 inline int getans(int l,int r,int k)

 75 {

 76     rc=lc=0;

 77     while(r)

 78     {

 79         rn[++rc]=h[r];

 80         r-=lowbit(r);

 81     }

 82     while(l)

 83     {

 84         ln[++lc]=h[l];

 85         l-=lowbit(l);

 86     }

 87     return query(1,num,k);

 88 }

 89 

 90 inline void read()

 91 {

 92     scanf("%d%d",&n,&m);

 93     for(int i=1;i<=n;i++)

 94     {

 95         scanf("%d",&a[i]);

 96         bh[++gs]=a[i];

 97     }

 98     char str[4];

 99     for(int i=1;i<=m;i++)

100     {

101         scanf("%s",str);

102         if(str[0]=='Q')

103         {

104             dat[i][0]=0;

105             for(int j=1;j<=3;j++) scanf("%d",&dat[i][j]);

106         }

107         else

108         {

109             dat[i][0]=1;

110             scanf("%d%d",&dat[i][1],&dat[i][2]);

111             bh[++gs]=dat[i][2];

112         }

113     }

114 }

115 

116 inline void go()

117 {

118     sort(bh+1,bh+1+gs);

119     num=unique(bh+1,bh+1+gs)-bh-1;

120     for(int i=1;i<=n;i++) a[i]=lower_bound(bh+1,bh+1+num,a[i])-bh;

121     build(1,num,h[0]);

122     for(int i=1;i<=n;i++) modify(i,a[i],1);

123     for(int i=1;i<=m;i++)

124     {

125         if(dat[i][0]==0) printf("%d\n",bh[getans(dat[i][1]-1,dat[i][2],dat[i][3])]);

126         else

127         {

128             int pos=lower_bound(bh+1,bh+1+num,dat[i][2])-bh;

129             modify(dat[i][1],a[dat[i][1]],-1);

130             a[dat[i][1]]=pos;

131             modify(dat[i][1],a[dat[i][1]],1);

132         }

133     }

134 }

135 

136 int main()

137 {

138     read(),go();

139     return 0;

140 }

 

 

你可能感兴趣的:(树状数组)