形形色色的水果姐逛水果街——codevs水果姐逛水果街1-3:线段树与ST表

这次的注释可能略显繁琐,但是是我认真写的帮助大家理解也帮助自己回顾,本文中重复部分不再添加注释,还请查看之前的部分作参考。

水果姐逛水果街Ⅰ

http://codevs.cn/problem/3304/

//线段树版本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m,a,b,tot;
int num[200010];
struct inte
{
    int l,r;
    ll maxn,minx,lans,rans;//区间最大值,最小值,区间内从左向右的答案,从右向左的答案 
}tree[1000010];
void update(int now)
{
    tree[now].maxn=max(tree[now<<1].maxn,tree[now<<1|1].maxn);
    tree[now].minx=min(tree[now<<1].minx,tree[now<<1|1].minx);
    ll tmp1=tree[now<<1|1].maxn-tree[now<<1].minx;
    ll tmp2=tree[now<<1].maxn-tree[now<<1|1].minx;
    tree[now].lans=max(tmp1,max(tree[now<<1].lans,tree[now<<1|1].lans));//右儿子的最大值-左儿子的最小值(跨越左右子区间从左向右),与左右儿子中的从左向右答案取max 
    tree[now].rans=max(tmp2,max(tree[now<<1].rans,tree[now<<1|1].rans));//左儿子的最大值-右儿子的最小值(跨越左右子区间从右向左),与左右儿子中的从右向左答案取max
}
void build(int now,int l,int r)
{
    tree[now].l=l;
    tree[now].r=r;
    if(l==r)
    {
        tree[now].maxn=num[l];
        tree[now].minx=num[l];
        return;
    }
    int mid=(l+r)>>1;
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    update(now);
}
inte query(int now,int l,int r)//结构体类型,便于返回多个变量 
{
    if(tree[now].l>=l&&tree[now].r<=r)
    return tree[now];
    inte tmp,tmp1,tmp2;
    tmp1=(inte){0,0,-1e9+7,1e9+7,0,0};//初始化 
    tmp2=(inte){0,0,-1e9+7,1e9+7,0,0};
    int mid=(tree[now].l+tree[now].r)>>1;
    if(l<=mid)
    tmp1=query(now<<1,l,r);
    if(r>mid)
    tmp2=query(now<<1|1,l,r);
    tmp.lans=max(tmp1.lans,max(tmp2.lans,tmp2.maxn-tmp1.minx));//左儿子递归的从左向右答案,右儿子递归的从左向右答案,与右儿子的最大值-左儿子的最小值取max 
    tmp.rans=max(tmp1.rans,max(tmp2.rans,tmp1.maxn-tmp2.minx));//左儿子递归的从右向左答案,右儿子递归的从右向左答案,与左儿子的最大值-右儿子的最小值取max
    tmp.maxn=max(tmp1.maxn,tmp2.maxn);
    tmp.minx=min(tmp1.minx,tmp2.minx);
    return tmp;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&num[i]);
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        if(a<=b)
        printf("%lld\n",query(1,a,b).lans);
        else printf("%lld\n",query(1,b,a).rans);
    }
    return 0;
}



//ST表版本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,a,b,tot,ans;
int num[200010],lans[200010][20],rans[200010][20],maxs[200010][20],mins[200010][20];
void build()//预处理 
{
    for(int i=1;i<=n;i++)
    maxs[i][0]=num[i],mins[i][0]=num[i];
    for(int j=1;(1<<j)<=n;j++)
    for(int i=1;i+(1<<j)-1<=n;i++)
    {
        maxs[i][j]=max(maxs[i][j-1],maxs[i+(1<<(j-1))][j-1]);//向后跳2^(j-1)步的最大值,向后跳2^j(向后跳2^(j-1)步再跳2^(j-1))步的最大值取max 
        mins[i][j]=min(mins[i][j-1],mins[i+(1<<(j-1))][j-1]);//向后跳2^(j-1)步的最小值,向后跳2^j步的最小值取min 
        lans[i][j]=max(maxs[i+(1<<(j-1))][j-1]-mins[i][j-1],max(lans[i][j-1],lans[i+(1<<(j-1))][j-1]));
        //向后跳2^j步的最大值-向后跳2^(j-1)步的最小值,向后跳2^(j-1)步的从左向右的答案与向后跳2^j步的从左向右的答案取max 
        rans[i][j]=max(maxs[i][j-1]-mins[i+(1<<(j-1))][j-1],max(rans[i+(1<<(j-1))][j-1],rans[i][j-1]));
        //向后跳2^(j-1)步的最大值-向后跳2^j步的最小值,向后跳2^j步的从右向左的答案与向后跳2^(j-1)步的从右向左的答案取max
    }
}
int query_1(int l,int r)
{
    int k=0,ans=0,minx=1e9+7;
    while((1<<(k+1))<=r-l+1)
    k++;
    for(int i=k;i>=0;i--)
    {
        if(l+(1<<i)-1<=r)
        {
            ans=max(ans,max(lans[l][i],maxs[l][i]-minx));//l向后跳2^i步的从左向右的答案,l向后跳2^i步的最大值-上一个位置的l(未向后跳2^(i+1)步)向后跳2^(i+1)步的最小值 
            minx=min(minx,mins[l][i]);                   //即此次跳跃区间的最大值-上一个跳跃区间的最小值 
            l+=(1<<i);
        }
    }
    return ans;
}
int query_2(int l,int r)
{
    int k=0,ans=0,maxn=-1e9+7;
    while((1<<(k+1))<=r-l+1)
    k++;
    for(int i=k;i>=0;i--)
    {
        if(l+(1<<i)-1<=r)
        {
            ans=max(ans,max(rans[l][i],maxn-mins[l][i]));//l向后跳2^i步的从右向左的答案,上一个位置的l(未向后跳2^(i+1)步)向后跳2^(i+1)步的最大值-l向后跳2^i步的最小值
            maxn=max(maxn,maxs[l][i]);                   //即上一个跳跃区间的最大值-此次跳跃区间的最小值
            l+=(1<<i);
        }
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&num[i]);
    build();
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        ans=0;
        scanf("%d%d",&a,&b);
        if(a<=b)
        printf("%d\n",query_1(a,b));
        else
        printf("%d\n",query_2(b,a));
    }
    return 0;
}


水果姐逛水果街Ⅱ

http://codevs.cn/problem/3305/

//线段树版本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m,tot,ru,rv,a,b;
int num[200010],first[400010],nxt[400010],deep[200010],top[200010],f[200010],siz[200010],son[200010],toseg[200010],totre[200010];
struct edge
{
    int u,v;
}l[400010];
struct inte 
{
    int l,r;
    ll lans,rans,maxn,minx;
}tree[1000010]; 
void add(int f,int t)
{
    l[++tot]=(edge){f,t};
    nxt[tot]=first[f];
    first[f]=tot;
}
void dfs_1(int k,int fa,int d)//树链剖分 
{
    deep[k]=d;
    f[k]=fa;
    siz[k]=1;
    for(int i=first[k];i!=-1;i=nxt[i])
    {
        int x=l[i].v;
        if(x==fa)
        continue;
        dfs_1(x,k,d+1);
        siz[k]+=siz[x];
        if(!son[k]||siz[x]>siz[son[k]])
        son[k]=x;
    }
}
void dfs_2(int k,int num)
{
    top[k]=num;
    toseg[k]=++tot;
    totre[toseg[k]]=k;
    if(!son[k])
    return;
    dfs_2(son[k],num);
    for(int i=first[k];i!=-1;i=nxt[i])
    {
        int x=l[i].v;
        if(x!=son[k]&&x!=f[k])
        dfs_2(x,x);
    }
}
void update(int now)//参考水果姐I理解 
{
    tree[now].maxn=max(tree[now<<1].maxn,tree[now<<1|1].maxn);
    tree[now].minx=min(tree[now<<1].minx,tree[now<<1|1].minx);
    tree[now].lans=max(max(tree[now<<1].lans,tree[now<<1|1].lans),tree[now<<1|1].maxn-tree[now<<1].minx);
    tree[now].rans=max(max(tree[now<<1].rans,tree[now<<1|1].rans),tree[now<<1].maxn-tree[now<<1|1].minx);
}
void build(int now,int l,int r)
{
    tree[now].l=l;
    tree[now].r=r;
    if(l==r)
    {
        tree[now].maxn=num[totre[l]];
        tree[now].minx=num[totre[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    update(now);
}
inte ask(int now,int l,int r)
{
    if(tree[now].l>=l&&tree[now].r<=r)
    {
        return tree[now];
    }
    inte tmp,tmp1,tmp2;
    tmp1=(inte){0,0,-1e9+7,-1e9+7,-1e9+7,1e9+7};
    tmp2=(inte){0,0,-1e9+7,-1e9+7,-1e9+7,1e9+7};
    int mid=(tree[now].l+tree[now].r)>>1;
    if(l<=mid)
    tmp1=ask(now<<1,l,r);
    if(r>mid)
    tmp2=ask(now<<1|1,l,r);
    tmp.lans=max(tmp1.lans,max(tmp2.lans,tmp2.maxn-tmp1.minx));
    tmp.rans=max(tmp1.rans,max(tmp2.rans,tmp1.maxn-tmp2.minx));
    tmp.maxn=max(tmp1.maxn,tmp2.maxn);
    tmp.minx=min(tmp1.minx,tmp2.minx);
    return tmp;
}
ll find_ans(int x,int y)//转换器 
{
    if(toseg[x]>toseg[y])//若x在线段树上的编号>y在线段树上的编号,即x在原树上的深度>y在原树上的深度 
    return ask(1,toseg[y],toseg[x]).rans;//返回原树从y向x走的线段树从右向左的答案 
    else return ask(1,toseg[x],toseg[y]).lans;//返回原树从x向y走的线段树从左向右的答案 
}
ll find_max(int x,int y)
{
    if(toseg[x]>toseg[y])
    return ask(1,toseg[y],toseg[x]).maxn;
    else return ask(1,toseg[x],toseg[y]).maxn; 
}
ll find_min(int x,int y)
{
    if(toseg[x]>toseg[y])
    return ask(1,toseg[y],toseg[x]).minx;
    else return ask(1,toseg[x],toseg[y]).minx; 
}
ll query(int x,int y)//这里是由x向y走 
{
    ll ans=-1e9+7,maxn=-1e9+7,minx=1e9+7;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]>deep[top[y]])
        {
            ans=max(ans,find_ans(x,top[x]));
            minx=min(minx,find_min(x,top[x]));
            ans=max(ans,maxn-minx);//从y向lca跳经过区间的最大值-从x向lca跳经过区间内的最小值 
            x=f[top[x]];
        }
        else
        {
            ans=max(ans,find_ans(top[y],y));
            maxn=max(maxn,find_max(top[y],y));
            ans=max(ans,maxn-minx);
            y=f[top[y]];
        }
    }
    //注意x与y位置已经被更新至同一条重链上 
    ans=max(ans,find_ans(x,y));//x与y在同一条重链上时,x-y区间内部的答案 
    ans=max(ans,max(find_max(x,y)-minx,maxn-find_min(x,y)));//x-y区间内最大值-向上跳至同一条重链时从x向lca跳经过区间内的最小值,与向上跳至同一条重链时从y向lca跳经过区间内的最大值-x-y区间内最小值取max 
    ans=max(ans,maxn-minx);//向上跳至同一条重链时从y向lca跳经过区间内的最大值-从x向lca跳经过区间内的最小值
    return ans;
}
int main()
{
    memset(first,-1,sizeof(first));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&num[i]);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&ru,&rv);//树中为双向边 
        add(ru,rv);
        add(rv,ru);
    }
    tot=0;
    dfs_1(1,0,1);
    dfs_2(1,1);
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        printf("%lld\n",query(a,b));
    }
    return 0;
}



//ST表版本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,ru,rv,a,b,lca,tot;
int num[200010],first[400010],nxt[400010],deep[200010],anc[200010][21],lans[200010][21],rans[200010][21],maxs[200010][21],mins[200010][21];
struct edge
{
    int u,v;
}l[400010];
void add(int f,int t)
{
    l[++tot]=(edge){f,t};
    nxt[tot]=first[f];
    first[f]=tot;
}
void dfs(int k,int fa)
{
    deep[k]=deep[fa]+1;
    anc[k][0]=fa;//k向上跳2^0(1)步的祖先为fa 
    maxs[k][0]=max(num[k],num[fa]);//k向上跳2^0步的最大值 
    mins[k][0]=min(num[k],num[fa]);//k向上跳2^0步的最小值
    lans[k][0]=max(num[fa]-num[k],0);//k向上跳2^0步的从下向上的答案 
    rans[k][0]=max(num[k]-num[fa],0);//k向上跳2^0步的从上向下的答案 
    for(int i=1;anc[k][i-1];i++)
    {
        anc[k][i]=anc[anc[k][i-1]][i-1];
        maxs[k][i]=max(maxs[k][i-1],maxs[anc[k][i-1]][i-1]);
        mins[k][i]=min(mins[k][i-1],mins[anc[k][i-1]][i-1]);
        lans[k][i]=max(maxs[anc[k][i-1]][i-1]-mins[k][i-1],max(lans[k][i-1],lans[anc[k][i-1]][i-1]));
        rans[k][i]=max(maxs[k][i-1]-mins[anc[k][i-1]][i-1],max(rans[k][i-1],rans[anc[k][i-1]][i-1]));
    }
    /*for(int i=1;anc[k][i-1];i++)//不同的预处理方式 
    {
        anc[k][i]=anc[anc[k][i-1]][i-1];
    }
    for(int j=1;(1<<j)<=deep[k]-1;j++)
    {
        maxs[k][j]=max(maxs[k][j-1],maxs[anc[k][j-1]][j-1]);
        mins[k][j]=min(mins[k][j-1],mins[anc[k][j-1]][j-1]);
        lans[k][j]=max(maxs[anc[k][j-1]][j-1]-mins[k][j-1],max(lans[k][j-1],lans[anc[k][j-1]][j-1]));
        rans[k][j]=max(maxs[k][j-1]-mins[anc[k][j-1]][j-1],max(rans[k][j-1],rans[anc[k][j-1]][j-1]));
    }*/
    for(int i=first[k];i!=-1;i=nxt[i])
    {
        int x=l[i].v;
        if(!deep[x])
        {
            dfs(x,k);
        }
    }
}
int count(int x,int y)
{
    int k=0,ans=0,minx=1e9+7,maxn=-1e9+7;
    int d=deep[x]-deep[lca];
    if(d>0)
    {
        for(int i=20;i>=0;i--)
        {
            if(d&(1<<i))
            {
                ans=max(ans,max(lans[x][i],maxs[x][i]-minx));
                minx=min(minx,mins[x][i]);
                x=anc[x][i];
            }
        }
    }
    d=deep[y]-deep[lca];
    if(d>0)
    {
        for(int i=20;i>=0;i--)
        {
            if(d&(1<<i))
            {
                ans=max(ans,max(rans[y][i],maxn-mins[y][i]));
                maxn=max(maxn,maxs[y][i]);
                y=anc[y][i];
            }
        }
    }
    return max(ans,maxn-minx);
}
/*int count(int x,int y)//不同的统计方式 
{
    int k=0,ans=0,minx=1e9+7,maxn=-1e9+7;
    if(deep[x]>deep[lca])
    {
        int l=1,r=deep[x]-deep[lca]+1;
        while((1<<(k+1))<=r-l)
        k++;
        for(int i=k;i>=0;i--)
        {
            if(l+(1<<i)<=r)
            {
                ans=max(ans,max(lans[x][i],maxs[x][i]-minx));
                minx=min(minx,mins[x][i]);
                x=anc[x][i];
                l+=(1<<i);
            }
        }
    }
    if(deep[y]>deep[lca])
    {
        k=0;
        int l=1,r=deep[y]-deep[lca]+1;
        while((1<<(k+1))<=r-l)
        k++;
        for(int i=k;i>=0;i--)
        {
            if(l+(1<<i)<=r)
            {
                ans=max(ans,max(rans[y][i],maxn-mins[y][i]));
                maxn=max(maxn,maxs[y][i]);
                y=anc[y][i];
                l+=(1<<i);
            }
        }
    }
    return max(ans,maxn-minx);
}*/
int ask_lca(int x,int y)//倍增lca 
{
    if(deep[x]<deep[y])
    swap(x,y);
    if(deep[x]>deep[y])
    {
        int d=deep[x]-deep[y];
        for(int i=0;i<=20;i++)
        {
            if(d&(1<<i))
            x=anc[x][i];
        }
    }
    if(x!=y)
    {
        for(int i=20;i>=0;i--)
        {
            if(anc[x][i]!=anc[y][i])
            {
                x=anc[x][i];
                y=anc[y][i];
            }
        }
    }
    if(x==y)
    lca=x;
    else lca=anc[x][0];
    return count(a,b);
}
int main()
{
    memset(first,-1,sizeof(first));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&num[i]);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&ru,&rv);
        add(ru,rv);
        add(rv,ru);
    }
    tot=0;
    dfs(1,0);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        tot=0;
        scanf("%d%d",&a,&b);
        printf("%d\n",ask_lca(a,b));
    }
    return 0;
}


水果姐逛水果街Ⅲ

http://codevs.cn/problem/3306/
这个好像只能用线段树做了…
主体与II完全相同,只需要加个point_set就好啦.

//线段树版本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m,tot,ru,rv,a,b,p;
int num[200010],first[400010],nxt[400010],deep[200010],top[200010],f[200010],siz[200010],son[200010],toseg[200010],totre[200010];
struct edge
{
    int u,v;
}l[400010];
struct inte 
{
    int l,r;
    ll lans,rans,maxn,minx;
}tree[1000010]; 
void add(int f,int t)
{
    l[++tot]=(edge){f,t};
    nxt[tot]=first[f];
    first[f]=tot;
}
void dfs_1(int k,int fa,int d)
{
    deep[k]=d;
    f[k]=fa;
    siz[k]=1;
    for(int i=first[k];i!=-1;i=nxt[i])
    {
        int x=l[i].v;
        if(x==fa)
        continue;
        dfs_1(x,k,d+1);
        siz[k]+=siz[x];
        if(!son[k]||siz[x]>siz[son[k]])
        son[k]=x;
    }
}
void dfs_2(int k,int num)
{
    top[k]=num;
    toseg[k]=++tot;
    totre[toseg[k]]=k;
    if(!son[k])
    return;
    dfs_2(son[k],num);
    for(int i=first[k];i!=-1;i=nxt[i])
    {
        int x=l[i].v;
        if(x!=son[k]&&x!=f[k])
        dfs_2(x,x);
    }
}
void update(int now)//参考水果姐2理解
{
    tree[now].maxn=max(tree[now<<1].maxn,tree[now<<1|1].maxn);
    tree[now].minx=min(tree[now<<1].minx,tree[now<<1|1].minx);
    tree[now].lans=max(max(tree[now<<1].lans,tree[now<<1|1].lans),tree[now<<1|1].maxn-tree[now<<1].minx);
    tree[now].rans=max(max(tree[now<<1].rans,tree[now<<1|1].rans),tree[now<<1].maxn-tree[now<<1|1].minx);
}
void build(int now,int l,int r)
{
    tree[now].l=l;
    tree[now].r=r;
    if(l==r)
    {
        tree[now].maxn=num[totre[l]];
        tree[now].minx=num[totre[l]];
        return;
    }
    int mid=(l+r)>>1;
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    update(now);
}
void point_set(int now,int pos,ll value)
{
    if(tree[now].l==tree[now].r)
    {
        tree[now].maxn=value;
        tree[now].minx=value;
        return;
    }
    int mid=(tree[now].l+tree[now].r)>>1;
    if(pos<=mid)
    point_set(now<<1,pos,value);
    else
    point_set(now<<1|1,pos,value);
    update(now);
}
inte ask(int now,int l,int r)
{
    if(tree[now].l>=l&&tree[now].r<=r)
    {
        return tree[now];
    }
    inte tmp,tmp1,tmp2;
    tmp1=(inte){0,0,-1e9+7,-1e9+7,-1e9+7,1e9+7};
    tmp2=(inte){0,0,-1e9+7,-1e9+7,-1e9+7,1e9+7};
    int mid=(tree[now].l+tree[now].r)>>1;
    if(l<=mid)
    tmp1=ask(now<<1,l,r);
    if(r>mid)
    tmp2=ask(now<<1|1,l,r);
    tmp.lans=max(tmp1.lans,max(tmp2.lans,tmp2.maxn-tmp1.minx));
    tmp.rans=max(tmp1.rans,max(tmp2.rans,tmp1.maxn-tmp2.minx));
    tmp.maxn=max(tmp1.maxn,tmp2.maxn);
    tmp.minx=min(tmp1.minx,tmp2.minx);
    return tmp;
}
ll find_ans(int x,int y)
{
    if(toseg[x]>toseg[y])
    return ask(1,toseg[y],toseg[x]).rans;
    else return ask(1,toseg[x],toseg[y]).lans;
}
ll find_max(int x,int y)
{
    if(toseg[x]>toseg[y])
    return ask(1,toseg[y],toseg[x]).maxn;
    else return ask(1,toseg[x],toseg[y]).maxn; 
}
ll find_min(int x,int y)
{
    if(toseg[x]>toseg[y])
    return ask(1,toseg[y],toseg[x]).minx;
    else return ask(1,toseg[x],toseg[y]).minx; 
}
ll query(int x,int y)
{
    ll ans=-1e9+7,maxn=-1e9+7,minx=1e9+7;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]>deep[top[y]])
        {
            ans=max(ans,find_ans(x,top[x]));
            minx=min(minx,find_min(x,top[x]));
            ans=max(ans,maxn-minx);
            x=f[top[x]];
        }
        else
        {
            ans=max(ans,find_ans(top[y],y));
            maxn=max(maxn,find_max(top[y],y));
            ans=max(ans,maxn-minx);
            y=f[top[y]];
        }
    }
    ans=max(ans,find_ans(x,y));
    ans=max(ans,max(find_max(x,y)-minx,maxn-find_min(x,y)));
    ans=max(ans,maxn-minx);
    return ans;
}
int main()
{
    memset(first,-1,sizeof(first));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&num[i]);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&ru,&rv);
        add(ru,rv);
        add(rv,ru);
    }
    tot=0;
    dfs_1(1,0,1);
    dfs_2(1,1);
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&p,&a,&b);
        if(p==0)
        point_set(1,toseg[a],b);
        if(p==1)
        printf("%lld\n",query(a,b));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值