[主席树]ZOJ2112 Dynamic Rankings

题意:n个数,q个询问 (n<=50000, q<=10000)

Q x y z 代表询问[x, y]区间里的第z小的数

C x y    代表将(从左往右数)第x个数变成y

 

上篇介绍了在[x, y]区间内查询第z小的数的方法(静态主席树)

本题有更新操作

 

若仍用上篇的做法,

每次更新一个数,需要更新的是T[i], T[i+1]... ...T[n](该数所在的树以及它后面的所有树)

因为每棵树T[i]所记录的都是前缀(1到i的数出现的次数) 因此,改变i,会影响i到n的所有树

这样,每次更新的复杂度最坏为O($n$),最坏更新q次即为O($n\times m$) 复杂度相当庞大,很明显这样做是不行的

 

那怎么办呢?

我们可以发现,对于改变i处的数这个操作,对于T[i], T[i+1]... ...T[n]这些树的影响是相同的

  都只改变了  “原来i处的数 的数量”  和  “现在i处的数 的数量” 这两个值而已

因此,我们要用主席树来维护每个位置,对于每个位置建立线段树,(而非每个位置及其前缀)

再用树状数组来记录更新,维护前缀和,每次更新$logn$棵树

 

将每个位置建一棵线段树的好处是 使得每个位置可以相加减,那么就相当于用树状数组来询问区间和了

 

 

模板是kuangbin

query用非递归的形式节约时间orz...

[主席树]ZOJ2112 Dynamic Rankings
  1 #include <bits/stdc++.h>

  2 using namespace std;

  3 typedef long long LL;

  4 #define lson l, m

  5 #define rson m+1, r

  6 const int N=60005;

  7 int a[N], wz[N];

  8 int T[N], L[N<<5], R[N<<5], c[N<<5];

  9 int S[N];

 10 int n, m, tot;

 11 struct node

 12 {

 13     int l, r, k;

 14     bool Q;

 15 }op[10010];

 16 

 17 int build(int l, int r)

 18 {

 19     int rt=tot++;

 20     c[rt]=0;

 21     if(l!=r)

 22     {

 23         int m=(l+r)>>1;

 24         L[rt]=build(lson);

 25         R[rt]=build(rson);

 26     }

 27     return rt;

 28 }

 29 

 30 int Insert(int rt, int pos, int val)

 31 {

 32     int newrt=tot, tmp=tot++;

 33     int l=0, r=m-1;

 34     c[newrt]=c[rt]+val;

 35     while(l<r)

 36     {

 37         int m=(l+r)>>1;

 38         if(pos<=m)

 39         {

 40             L[newrt]=tot++;

 41             R[newrt]=R[rt];

 42             newrt=L[newrt];

 43             rt=L[rt];

 44             r=m;

 45         }

 46         else

 47         {

 48             R[newrt]=tot++;

 49             L[newrt]=L[rt];

 50             newrt=R[newrt];

 51             rt=R[rt];

 52             l=m+1;

 53         }

 54         c[newrt]=c[rt]+val;

 55     }

 56     return tmp;

 57 }

 58 

 59 int lowbit(int x)

 60 {

 61     return x&(-x);

 62 }

 63 

 64 int use[N];

 65 void add(int x, int pos, int val)

 66 {

 67     while(x<=n)

 68     {

 69         S[x]=Insert(S[x], pos, val);

 70         x+=lowbit(x);

 71     }

 72 }

 73 

 74 int sum(int x)

 75 {

 76     int ret=0;

 77     while(x>0)

 78     {

 79         ret+=c[L[use[x]]];

 80         x-=lowbit(x);

 81     }

 82     return ret;

 83 }

 84 

 85 int query(int left, int right, int k)

 86 {

 87     int lrt=T[left-1];

 88     int rrt=T[right];

 89     int l=0, r=m-1;

 90     for(int i=left-1;i;i-=lowbit(i))

 91         use[i]=S[i];

 92     for(int i=right;i;i-=lowbit(i))

 93         use[i]=S[i];

 94     while(l<r)

 95     {

 96         int m=(l+r)>>1;

 97         int tmp=sum(right)-sum(left-1)+c[L[rrt]]-c[L[lrt]];

 98         if(tmp>=k)

 99         {

100             r=m;

101             for(int i=left-1;i;i-=lowbit(i))

102                 use[i]=L[use[i]];

103             for(int i=right;i;i-=lowbit(i))

104                 use[i]=L[use[i]];

105             lrt=L[lrt];

106             rrt=L[rrt];

107         }

108         else

109         {

110             l=m+1;

111             k-=tmp;

112             for(int i=left-1;i;i-=lowbit(i))

113                 use[i]=R[use[i]];

114             for(int i=right;i;i-=lowbit(i))

115                 use[i]=R[use[i]];

116             lrt=R[lrt];

117             rrt=R[rrt];

118         }

119     }

120     return l;

121 }

122 

123 void Modify(int x, int p, int d)

124 {

125     while(x<=n)

126     {

127         S[x]=Insert(S[x], p, d);

128         x+=lowbit(x);

129     }

130 }

131 

132 int main()

133 {

134     int t;

135     scanf("%d", &t);

136     while(t--)

137     {

138         int q;

139         scanf("%d%d", &n, &q);

140         tot=0;

141         m=0;

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

143         {

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

145             wz[m++]=a[i];

146         }

147         for(int i=0;i<q;i++)

148         {

149             char s[10];

150             scanf("%s", s);

151             if(s[0]=='Q')

152             {

153                 scanf("%d%d%d", &op[i].l, &op[i].r, &op[i].k);

154                 op[i].Q=1;

155             }

156             else

157             {

158                 scanf("%d%d", &op[i].l, &op[i].r);

159                 op[i].Q=0;

160                 wz[m++]=op[i].r;

161             }

162         }

163         sort(wz, wz+m);

164         int mm=unique(wz, wz+m)-wz;

165         m=mm;

166         T[0]=build(0, m-1);

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

168             T[i]=Insert(T[i-1], lower_bound(wz, wz+m, a[i])-wz, 1);

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

170             S[i]=T[0];

171         for(int i=0;i<q;i++)

172         {

173             if(op[i].Q)

174                 printf("%d\n", wz[query(op[i].l, op[i].r, op[i].k)]);

175             else

176             {

177                 Modify(op[i].l, lower_bound(wz, wz+m, a[op[i].l])-wz, -1);

178                 Modify(op[i].l, lower_bound(wz, wz+m, op[i].r)-wz, 1);

179                 a[op[i].l]=op[i].r;

180             }

181         }

182     }

183     return 0;

184 }
ZOJ 2112

 

你可能感兴趣的:(dynamic)