2014/11/15
老规矩,想学主席树的这边走疯狂的橡树(推荐),这里只写点自己敲代码的时候遇到的问题。
这颗树是从昨天晚上8点开始敲的,敲到了现在........
其他部分没问题:
先把数组离散化a[ i ]
建个空树
然后以每个a[ i ]节点为根节点根据前一个节点的树来建树。(每棵树省下一半的树节点)
然后问题来了:
建树状数组的时候,其实只理解到了用根节点来建,而每个根节点代表 a[ i ]这个值变动的状态,同样用树来表示,所以有这个根节点。
(每次变动相当于在原来的s[ i ]为根节点的树基础上在建一棵新树,再更新s[ i ],以保证a[ i ]节点 记录其变化动态的树的正确性)
(反正默认利用树状数组进行单点跟新也适用于 树的跟新就对了!= =)
我就记住 树状数组跟新树的同时,树的节点的值c[ ]也同时跟新(以这个节点为根节点的子树的 重量变化值,不是之前先算出来的值)
最后计算的时候再得出 sum = 原 sum +改动的值。树状数组学过就会明白的= =。
改动的值也不能只计算一棵树, 因为类似划分树,我们要计算出左子树的改动的值,而在 以s[ i ]为根的树中只记录了a[ i ]的变动状态。
而一棵左子树的变化的值取决于 1 - i颗树的变化的值的和(这个很好理解:你要计算数组1 -n 中一共变化了多少,就要去计算相加 其中每个元素各自变化了多少)
而树状数组则优化了这个过程。
敲代码的时候:
根据题目输入了 qs[ i ].l qs[ i]. r qs[ i ].k. 区间【l , r】 第k 大
但是跟新值的时候我图方便 输入了 qs[ i ].l qs[ i]. r ,用 qs[ i ].k = -inf 来区别,然后忘记了 qs[ i ].l qs[ i]. r 代表的值的意义:数组中第 x (qs[ i ].l )个节点的值跟新为 y(qs[ i]. r )
然后就莫名的跪了几次。。
郁闷到死啊啊啊啊啊:
好不容易敲完了,WA!WA!WA!
检查了半天( = 12小时)没发现错误,逼急了....我直接去上面某某的博客扒代码。
但是差不多啊 = = 分块的排除错误的可能性。。
最后:
大概就是计算改动的值的时候.....顺序反了一下....就反了一下.......Orzzzzzzzz
是树状数组没学精还是什么...不懂欸 啊喂 QAQ
(补:大概明白了些,因为后面循环里也有这个更新(我的顺序还是反了= =先 树R 在树 L-1)...就会把一些值覆盖)
AC: for(i=l-1,use=ua;i;i-=lowbit(i)) use[i]=ls[use[i]];
sb=sum(l-1);
for(i=r ,use=ub;i;i-=lowbit(i)) use[i]=ls[use[i]];
sa=sum(r);
WA:
for(i=r ,use=ub;i;i-=lowbit(i)) use[i]=ls[use[i]];
sa=sum(r); <pre name="code" class="cpp">for(i=l-1,use=ua;i;i-=lowbit(i)) use[i]=ls[use[i]];
sb=sum(l-1);
AC:for(i=l-1,use=ua;i;i-=lowbit(i)) use[i]=s[i];
sb=sum(l-1);
for(i=r ,use=ub;i;i-=lowbit(i)) use[i]=s[i];
sa=sum(r)<span style="font-family:Arial, Helvetica, sans-serif;">;</span>
WA: <pre style="word-wrap: break-word; white-space: pre-wrap;"> for( i = r,use = ub;i;i-=lowbit(i))use[i]= s[i];
suma = sum(r);
for( i = l-1,use = ua;i;i-=lowbit(i))use[i]= s[i];
sumb = sum(l-1);
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxm = 2555555;
const int maxn = 105000;
int ls[maxm],rs[maxm],c[maxm];
int a[maxn],s[maxn],h[maxn],T[maxn],ua[maxn],ub[maxn],*use;
int n, m, len, tot;
struct node{
int l, r, k;
}sq[10005];
void init()
{
sort(h,h+len);
len = unique(h,h+len) - h;
}
int Hash(int x)
{
return lower_bound(h,h+len,x) - h;
}
int lowbit(int x)
{
return x&(-x);
}
int build(int l,int r)
{
int rt = tot++ , mid;
c[rt] = 0;
if(l < r)
{
mid=(l+r)>>1;
ls[rt] = build(l,mid);
rs[rt] = build(mid+1,r);
}
return rt;
}
int sum(int x)
{
int ret = 0;
while(x)
{
ret += c[ls[use[x]]];
x-=lowbit(x);
}
return ret;
}
int update(int prt,int x ,int d)
{
int srt = tot++,tp = srt, l = 0, r =len-1, mid;
c[srt] = c[prt] + d;
while(l < r)
{
mid = (l+r)>>1;
if(x <= mid)
{
rs[srt] = rs[prt],ls[srt] = tot++;
prt = ls[prt];
srt = ls[srt];
r = mid;
}
else
{
ls[srt] = ls[prt],rs[srt] = tot++;
prt = rs[prt];
srt = rs[srt];
l = mid+1;
}
c[srt] = c[prt] + d;
}
return tp;
}
void Update(int x,int p,int d)
{
while(x <= n)
{
s[x] = update(s[x],p,d);
x += lowbit(x);
}
}
int que(int l ,int r,int k)
{
int lrt = T[l-1], srt = T[r], mid,ll = 0, rr = len-1, i, sa, sb;
for(i=l-1,use=ua;i;i-=lowbit(i)) use[i]=s[i];
sb=sum(l-1);
for(i=r ,use=ub;i;i-=lowbit(i)) use[i]=s[i];
sa=sum(r);
while(ll < rr)
{
mid =(ll+rr)>>1;
int tp =sa-sb +c[ls[srt]] - c[ls[lrt]];
if(k <= tp)
{
rr = mid;
lrt = ls[lrt];
srt = ls[srt];
for(i=l-1,use=ua;i;i-=lowbit(i)) use[i]=ls[use[i]];
sb=sum(l-1);
for(i=r ,use=ub;i;i-=lowbit(i)) use[i]=ls[use[i]];
sa=sum(r);
}
else
{
ll = mid+1;
k-=tp;
lrt = rs[lrt];
srt = rs[srt];
for(i=l-1,use=ua;i;i-=lowbit(i)) use[i]=rs[use[i]];
sb=sum(l-1);
for(i=r ,use=ub;i;i-=lowbit(i)) use[i]=rs[use[i]];
sa=sum(r);
}
}
return ll;
}
int main()
{
char ch[5];
int cas;
while(~scanf("%d",&cas))
{
while(cas--)
{
scanf("%d%d",&n,&m);
tot=0;
len=0;
for(int i = 1;i <= n; i++)
{
scanf("%d",&a[i]);
h[len++] = a[i];
}
for(int i = 0;i < m; i++)
{
scanf("%s",ch);
if(ch[0]=='Q')
{
scanf("%d%d%d",&sq[i].l,&sq[i].r,&sq[i].k);
}
else
{
scanf("%d%d",&sq[i].l,&sq[i].r);
sq[i].k = -inf;
h[len++] = sq[i].r;
}
}
init();
for(int i = 1;i <= n; i++)
s[i] = T[0];
T[0] = build(0,len-1);
for(int i = 1;i <= n; i++)
{
T[i] = update(T[i-1],Hash(a[i]),1);
}
for(int i = 0;i < m; i++)
{
if(sq[i].k == -inf)
{
Update(sq[i].l,Hash(a[sq[i].l]),-1);
Update(sq[i].l,Hash(sq[i].r),1);
a[sq[i].l] = sq[i].r;
}
else
{
printf("%d\n",h[que(sq[i].l,sq[i].r,sq[i].k)]);
}
}
}
}
return 0;
}