zkw线段树分析

来源:互联网 发布:windows启动错误恢复 编辑:程序博客网 时间:2024/05/18 02:54

具体内容见 ppt《统计的力量》

我目前能解决的问题有 

1.单点更新+区间求和/求最值

2.区间加减一个数+区间求最值

前缀和的前缀和无思路

1.单点更新+区间求和/求最值

注意此实现在存储的时候从 M+1 开始存

即对于下图 分别从5和9开始存储到6和14  另说明了zkw线段树在存储上是堆的结构


代码以hdu1754为例


#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>#include <cstring>using namespace std;const int maxn = 200000;int T[maxn<<2];int M;#define PUSHUP(x) T[x] = max(T[x+x],T[x+x+1])void build_tree(int n){    for(M=1;M <= n+1;M<<=1);    memset(T,0,sizeof(int) * (M+M));    for(int i = 1;i<=n;i++)        scanf("%d",T+i+M);    for(int i = (M+n)/2;i;i--)        PUSHUP(i);}int query_tree(int s,int t){    int ans = 0;    for(s = s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1)    {        if(~s&1) ans = max(ans,T[s^1]);        if(t&1) ans = max(ans,T[t^1]);    }    return ans;}void fix_tree(int p,int v){    for(T[p+=M]=v,p>>=1;p;p>>=1)        PUSHUP(p);}int main(){    int n,m,a,b;    char op[5];    while(~scanf("%d%d",&n,&m))    {        build_tree(n);        while(m--)        {            scanf("%s%d%d",op,&a,&b);            if(op[0]=='Q')printf("%d\n",query_tree(a,b));            else fix_tree(a,b);        }    }}

2.区间加减一个数+区间求最值

即利用差分思路

维护这样一种树

例如 a是b,c的父节点  那么 a = max(b,c);b -= a; c-=a;

上面是求最大值 求最小值改成min即可

以3 9 5 8为例

[图片]

求max的源码 min与之类似

#include <iostream>#include <cmath>#include <algorithm>#include <cstring>#include <cstdio>using namespace std;const int maxn = 200000;int T[maxn<<2];int M;void build_tree(int n){    for(M=1;M<=n+1;M<<=1);    memset(T,0,sizeof(int)*(M+M));    for(int i = 1;i<=n;i++)        scanf("%d",T+i+M);int A;    for(int i = (n+M)/2;i;i--)    {    A = max(T[i+i],T[i+i+1]);T[i+i] -= A;T[i+i+1] -=A;T[i] += A;}}int query_tree(int s,int t){    int Lans=0,Rans=0,ans=0;    for(s=s+M,t=t+M;s^t^1;s>>=1,t>>=1)    {        Lans += T[s];        Rans += T[t];        if(~s&1)Lans = max(Lans,T[s^1]);        if(t&1) Rans = max(Rans,T[t^1]);    }    ans = max(Lans,Rans);    while(s>1)ans += T[s>>=1];    return ans;}void fix_tree(int s,int t,int x){    int A;    for(s=s+M-1,t=t+M+1;s^t^1;s>>=1,t>>=1)    {        if(~s&1) T[s^1]+=x;        if(t&1) T[t^1]+=x;        A = max(T[s],T[s^1]);T[s]-=A;T[s^1]-=A;T[s>>1]+=A;        A = max(T[t],T[t^1]);T[t]-=A;T[t^1]-=A;T[t>>1]+=A;    }    for(;s>1;s>>=1)    {        A = max(T[s],T[s^1]);T[s]-=A;T[s^1]-=A;T[s>>1]+=A;    }}int main(){    int n;    cin >> n;    build_tree(n);//    for(int i = 0;i<=50;i++)//        cout << i<<":"<<T[i]<<endl;//    cout << query_tree(1,14)<<endl;//    fix_tree(2,4,2); //   fix_tree(3,5,2);//    fix_tree(4,6,2);    //    cout << query_tree(1,14)<<endl;    return 0;}





0 0
原创粉丝点击