随机挑战总结 Part3

本文记录了作者作为OIer进行随机跳题的实战过程,包括三道紫题的解题思路与代码实现,涉及二分答案、树形DP、矩阵乘法、分层图最短路及线段树维护等算法。

前言

今天纪中没有题目,所以闲的发慌又来随机跳题。
上次由于被 d a l a o dalao dalao们嘲讽说题目太简单了 q w q qwq qwq,所以这次跳的是3道紫题。
然而我的题目还是最简单的 q w q qwq qwq
再次准备被 d a l a o dalao dalao嘲讽 ( 2 / 2147483647 ) (2/2147483647) (2/2147483647)
主要还是太菜了。本来跳的第三题是一个分层图最短路,然后敲完样例没过,调试的我都要被恶心死了。还要跑两遍,读入字符串,而且我的方法还是会 M L E MLE MLE q w q qwq qwq然后两位大爷为了不让我这么尴尬就让我换了一道题结果又是一道水题。
随机跳题总结:我永远是最菜的OIer   qwq \color{white}\texttt{随机跳题总结:我永远是最菜的OIer qwq} 随机跳题总结:我永远是最菜的OIer qwq


题目:

  1. P 3554   [ P O I 2013 ] L U K − T r i u m p h a l   a r c h P3554\ [POI2013]LUK-Triumphal\ arch P3554 [POI2013]LUKTriumphal arch
  2. P 4838 P4838 P4838 P哥破解密码
  3. P 3259   [ J L O I 2014 ] P3259\ [JLOI2014] P3259 [JLOI2014]路径规划(放弃 q w q qwq qwq
  4. P 1712   [ N O I 2016 ] P1712\ [NOI2016] P1712 [NOI2016]区间

T1T2水的一匹,感觉要被嘲讽 q w q qwq qwq

在这里插入图片描述
Link:XXY巨爷的随机跳题Part3总结 \color{red}\texttt{Link:XXY巨爷的随机跳题Part3总结} Link:XXY巨爷的随机跳题Part3总结


题解

T1 P 3554   [ P O I 2013 ] L U K − T r i u m p h a l   a r c h P3554\ [POI2013]LUK-Triumphal\ arch P3554 [POI2013]LUKTriumphal arch

一道很简单的二分答案+树形 d p dp dp的题目。码量还贼小。
难度☆☆,不知道怎么被评上紫题的。
戳我:Link \color{blue}\texttt{戳我:Link} 戳我:Link


T2 P 4838 P4838 P4838 P哥破解密码

显然矩阵乘法,思路也很简单,不难想,写完结构体感觉为所欲为。
难度☆☆,不知道怎么被评上紫题的。
戳我:Link \color{blue}\texttt{戳我:Link} 戳我:Link


(伪)T3 P 3259   [ J L O I 2014 ] P3259\ [JLOI2014] P3259 [JLOI2014]路径规划

发现是分成图最短路,于是赶快去洛谷敲了一发 分层图最短路的模板
然后来做这道题,发现这不是一般的恶心啊啊啊啊啊啊啊啊啊啊啊。
难度☆☆☆☆☆,依然不知道怎么被评上紫题的不应该是黑题吗
WA代码就不放了,改天闲的发慌再来改吧。


T3 P 1712   [ N O I 2016 ] P1712\ [NOI2016] P1712 [NOI2016]区间

思维好题。退一番发现可以用线段树维护。然后就在线段树的标记细节上搞了比较久,最终总算是搞出来了。
难度☆☆☆,算是正常的紫题了。
戳我:Link \color{blue}\texttt{戳我:Link} 戳我:Link


代码

T1
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N=300010;
int n,x,y,tot,l,r,mid,f[N],head[N];

struct edge
{
    int to,next;
}e[N*2];

void add(int from,int to)
{
    e[++tot].to=to;
    e[tot].next=head[from];
    head[from]=tot;
}

void dp(int x,int fa)
{
    int sum=0;
    for (int i=head[x];~i;i=e[i].next)
    {
        int y=e[i].to;
        if (y!=fa)
        {
            dp(y,x);
            sum+=f[y]+1;
        }
    }
    f[x]=max(0,sum-mid);
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y); add(y,x);
    }
    l=0; r=n-1;
    while (l<=r)
    {
        mid=(l+r)/2;
        dp(1,0);
        if (!f[1]) r=mid-1;
            else l=mid+1;
    }
    printf("%d\n",r+1);
    return 0;
}
T2
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;

const ll MOD=19260817;
int n,m;

struct matrix
{
    ll a[4][4];
}f,A,a;
 
matrix operator *(matrix a,matrix b)
{
    matrix c;
    memset(c.a,0,sizeof(c.a));
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
      		for(int k=1;k<=3;k++)
          		c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%MOD;
    return c;
}

void power(int M)
{
    for (;M;M>>=1,a=a*a)
        if (M&1) f=f*a;
}

int main()
{
    //A.a[1][3]=A.a[2][1]=A.a[3][1]=A.a[3][2]=A.a[3][3]=1;
    A.a[3][1]=A.a[1][2]=A.a[1][3]=A.a[2][3]=A.a[3][3]=1;
    scanf("%d",&m);
    while (m--)
    {
        memcpy(a.a,A.a,sizeof(A.a));
        memset(f.a,0,sizeof(f.a));
        f.a[1][1]=f.a[1][3]=1;
        scanf("%d",&n);
        power(n-1);
        printf("%lld\n",(f.a[1][1]+f.a[1][2]+f.a[1][3])%MOD);
    }
    return 0;
}
T3
#include <cstdio>
#include <algorithm>
using namespace std;

const int N=500010,Inf=2e9;
int n,m,maxn,ans=Inf,b[N*2];

struct node
{
    int l,r,len;
}a[N];

struct Tree
{
    int l,r,maxn,lazy;
}tree[N*8];

bool cmp(node x,node y)
{
    return x.len<y.len;
}

void build(int x)
{
    if (tree[x].l==tree[x].r) return;
    int mid=(tree[x].l+tree[x].r)/2;
    tree[x*2].l=tree[x].l;
    tree[x*2].r=mid;
    tree[x*2+1].l=mid+1;
    tree[x*2+1].r=tree[x].r;
    build(x*2); build(x*2+1);
}

void pushdown(int x)
{
    if (tree[x].lazy)
    {
        tree[x*2].lazy+=tree[x].lazy;
        tree[x*2+1].lazy+=tree[x].lazy;
        tree[x*2].maxn+=tree[x].lazy;
        tree[x*2+1].maxn+=tree[x].lazy;
        tree[x].lazy=0;
    }
}

void add(int x,int l,int r)
{
    if (tree[x].l==l && tree[x].r==r)
    {
        tree[x].lazy++;
        tree[x].maxn++;
        return;
    }
    pushdown(x);
    int mid=(tree[x].l+tree[x].r)/2;
    if (r<=mid) add(x*2,l,r);
    else if (l>mid) add(x*2+1,l,r);
    else add(x*2,l,mid),add(x*2+1,mid+1,r);
    tree[x].maxn=max(tree[x*2].maxn,tree[x*2+1].maxn);
}

void del(int x,int l,int r)
{
    if (tree[x].l==l && tree[x].r==r)
    {
        tree[x].lazy--;
        tree[x].maxn--;
        return;
    }
    pushdown(x);
    int mid=(tree[x].l+tree[x].r)/2;
    if (r<=mid) del(x*2,l,r);
    else if (l>mid) del(x*2+1,l,r);
    else del(x*2,l,mid),del(x*2+1,mid+1,r);
    tree[x].maxn=max(tree[x*2].maxn,tree[x*2+1].maxn);
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].l,&a[i].r);
        a[i].len=a[i].r-a[i].l;
        b[2*i-1]=a[i].l; b[2*i]=a[i].r;
    }
    sort(b+1,b+1+n+n);
    int tot=unique(b+1,b+1+n+n)-b-1;
    for (int i=1;i<=n;i++)
    {
        a[i].l=lower_bound(b+1,b+1+tot,a[i].l)-b;
        a[i].r=lower_bound(b+1,b+1+tot,a[i].r)-b;
        if (a[i].r>maxn) maxn=a[i].r;
    }
    tree[1].l=1; tree[1].r=maxn;
    build(1);
    sort(a+1,a+1+n,cmp);
    for (int r=1,l=0;r<=n;r++)
    {
        add(1,a[r].l,a[r].r);
        if (tree[1].maxn>=m)
        {
            do
            {
                l++;
                del(1,a[l].l,a[l].r);
            }while (tree[1].maxn>=m);
            if (a[r].len-a[l].len<ans) ans=a[r].len-a[l].len;
        }
    }
    if (ans<Inf) printf("%d\n",ans);
        else printf("-1");
    return 0;
}
<think>我们正在讨论一个用于数据增强的变换:BBoxSafeRandomCrop。这个变换的主要目的是在随机裁剪图像的同时,确保边界框(Bounding Box)不会被裁剪掉。参数包括erosion_rate=0.2和p=0.1,其中p表示应用该变换的概率(10%),而erosion_rate=0.2是一个关键参数,用于控制边界框的“侵蚀”程度,以便在裁剪时留出安全区域。 原理分析: 1. 目标:随机裁剪图像,但要保证边界框内的目标物体仍然在裁剪后的图像内。 2. 挑战:如果随机裁剪的区域完全覆盖了边界框,那么边界框内的物体就会被保留。但随机选择的裁剪区域可能不会覆盖整个边界框,导致物体部分或全部被裁掉。 3. 解决方案:通过“侵蚀”边界框(即缩小边界框)来定义一个安全区域,然后确保裁剪区域至少覆盖这个安全区域的一部分(实际上,裁剪区域必须完全包含这个侵蚀后的边界框?或者至少覆盖边界框的中心区域?)。具体做法如下: 通常,BBoxSafeRandomCrop的工作流程: - 首先,根据给定的erosion_rate(侵蚀率)对原始边界框进行缩小操作。侵蚀率0.2表示将边界框的宽度和高度各缩小20%,从而在边界框内部形成一个更小的安全框(也叫做核心区域)。侵蚀操作通常是通过向内收缩边界框的边界来实现的,即: 新宽度 = 原始宽度 × (1 - 2 × erosion_rate) 新高度 = 原始高度 × (1 - 2 × erosion_rate) 注意:侵蚀率作用于两边(左和右,上和下),所以总共宽度减少的比例是2×erosion_rate。因此,侵蚀后的边界框位于原始边界框的中心,并且大小为原始大小的(1-2*erosion_rate)倍。 - 然后,随机生成一个裁剪区域(矩形),要求这个裁剪区域必须完全包含侵蚀后的边界框(即安全框)。这样,由于裁剪区域包含了侵蚀后的边界框,那么在原始边界框中,至少保留了中心区域(安全框)的部分,从而确保了目标物体不会被完全裁剪掉(因为安全框在原始边界框内部,而裁剪区域覆盖了安全框,所以原始边界框的中心部分一定在裁剪区域内)。 - 但是,注意:裁剪区域只需要包含整个侵蚀后的边界框?还是只需要与侵蚀后的边界框有交集?实际上,为了确保边界框内的物体不被丢失,通常要求裁剪区域完全包含侵蚀后的边界框(即安全框),而不是部分包含。因为如果只是部分包含,那么安全框的一部分可能被裁掉,导致边界框物体的一部分缺失,但我们希望至少保留中心部分。 然而,在具体实现中,我们可能会看到不同的做法。这里我们按照通常的安全裁剪逻辑:裁剪区域必须完全包含侵蚀后的边界框。这样,我们随机生成裁剪区域时,必须以侵蚀后的边界框的位置和大小作为约束条件。 具体步骤: 1. 计算每个边界框的侵蚀后版本(安全框)。 2. 确定一个能够包含所有安全框的最小矩形(如果有多个边界框)?但通常,这个变换可能是针对单个目标或者多个目标,但在随机裁剪中,我们通常要保证所有边界框的安全框都被包含。因此,我们可以这样: - 如果没有边界框,则进行普通的随机裁剪(或者跳过?根据实现)。 - 如果有边界框,则计算出所有安全框的整体外接矩形(即包含所有安全框的最小矩形)。然后,要求裁剪区域必须包含这个整体外接矩形(也就是包含所有安全框)。但是,这样可能会导致裁剪区域过大,因为要包含所有目标的安全框。另一种做法是,随机选择一个安全框作为基准,然后要求裁剪区域包含这个安全框(适用于单目标或者随机选择一个目标的情况)?实际实现可能不同。 在Albumentations库中(因为函数名与Albumentations风格相似)的BBoxSafeRandomCrop实现通常是针对多个边界框的:它要求裁剪区域必须包含所有侵蚀后的边界框(即每个边界框的安全框都在裁剪区域内)。因此,裁剪区域的左上角必须在所有安全框的左上角的左上方,裁剪区域的右下角必须在所有安全框的右下角的右下方。然后,在这个约束条件下随机选择裁剪区域。 但是,如果图像中有多个边界框且分布较散,那么包含所有安全框的裁剪区域可能非常大,甚至可能和原图差不多大,这样裁剪效果就不明显。因此,这种变换更适合于边界框相对集中的情况。 另外,参数p=0.1表示只有10%的概率执行该变换,其余时间不执行(即保留原图)。 总结:BBoxSafeRandomCrop(erosion_rate=0.2, p=0.1)的原理如下: 1. 以10%的概率应用该变换。 2. 对于每个边界框,使用侵蚀率0.2(即20%)进行侵蚀,得到安全框(大小为原始边界框的60%)。 3. 计算所有安全框的最小外接矩形(即所有安全框的并集的最小包围矩形)。 4. 在图像范围内,随机选择一个裁剪区域(矩形),要求该裁剪区域必须完全包含上述最小外接矩形(即所有安全框都在裁剪区域内)。 5. 然后,裁剪图像,并调整边界框的位置(因为图像被裁剪后,边界框的坐标需要相对于新图像的左上角重新计算)。 注意:调整边界框时,只需要将原始边界框减去裁剪区域的左上角坐标(并确保边界框被裁剪区域切割的部分被调整:实际上,由于裁剪区域完全包含安全框,而安全框在原始边界框内部,因此原始边界框可能会被裁剪区域切割,但至少保留了中心部分。因此,裁剪后的边界框应该是原始边界框与裁剪区域的交集,同时,这个交集至少包含了安全框(即边界框的中心部分)所以不会完全丢失目标。 但是,边界框的调整:裁剪后,边界框可能被裁剪区域切割,所以需要将边界框限制在裁剪区域内,并且坐标转换到新的坐标系。 关于边界框的调整: - 裁剪区域的左上角坐标为(x_min_crop, y_min_crop),右下角为(x_max_crop, y_max_crop)。 - 对于原始边界框(bbox: [x_min, y_min, x_max, y_max]),裁剪后的新边界框为: new_x_min = max(x_min, x_min_crop) - x_min_crop new_y_min = max(y_min, y_min_crop) - y_min_crop new_x_max = min(x_max, x_max_crop) - x_min_crop new_y_max = min(y_max, y_max_crop) - y_min_crop - 然后,检查调整后的边界框是否有效(宽度和高度大于0)。由于裁剪区域完全包含了安全框,因此原始边界框的中心部分(安全框)一定在裁剪区域内,所以调整后的边界框至少包含安全框(大小不为0)。 然而,在裁剪过程中,我们可能会丢失边界框的周围部分,但中心部分被保留,因此不会完全丢失目标。 注意:侵蚀率的作用是确保安全框在原始边界框内部,这样即使裁剪区域只包含安全框,也能保证目标物体的中心部分被保留。侵蚀率越大,安全框越小,那么裁剪区域的选择范围就越大(因为安全框越小,包含它的区域就越多),但保留的物体区域就越少(只保留中心部分)。侵蚀率为0时,安全框等于原始边界框,那么裁剪区域必须完全包含原始边界框,这样就不会丢失边界框的任何部分。 因此,erosion_rate=0.2提供了一个折中:允许裁剪区域不包含边界框的边界部分(最多20%的边界可能被裁掉),但保留了中心区域(60%)。 实现步骤伪代码: if 随机数 < p: 1. 计算每个边界框的侵蚀后安全框: 对于每个bbox [x_min, y_min, x_max, y_max]: 宽度 = x_max - x_min 高度 = y_max - y_min 侵蚀宽度 = 宽度 * erosion_rate 侵蚀高度 = 高度 * erosion_rate 安全框: x_min_safe = x_min + erosion_width y_min_safe = y_min + erosion_height x_max_safe = x_max - erosion_width y_max_safe = y_max - erosion_height 注意:如果侵蚀后安全框的宽度或高度小于0,则可能需要进行修正(例如,设置为原始边界框的中心点,或跳过该边界框?),但通常侵蚀率较小,不会出现负数。 2. 计算所有安全框的最小外接矩形(即所有安全框的最小包围矩形): min_x = min(所有安全框的x_min_safe) min_y = min(所有安全框的y_min_safe) max_x = max(所有安全框的x_max_safe) max_y = max(所有安全框的y_max_safe) 3. 在满足以下条件的范围内随机选择裁剪区域的左上角: - 裁剪区域的左上角(x_crop_min, y_crop_min)必须满足: x_crop_min <= min_x 且 y_crop_min <= min_y - 裁剪区域的右下角(x_crop_max, y_crop_max)必须满足: x_crop_max >= max_x 且 y_crop_max >= max_y - 同时,裁剪区域不能超出原图范围。 因此,裁剪区域的左上角可选范围是:x坐标从0到min_x,y坐标从0到min_y;裁剪区域的右下角可选范围是:x坐标从max_x到原图宽度,y坐标从max_y到原图高度。 4. 随机选择裁剪区域的左上角(x_crop_min, y_crop_min)和右下角(x_crop_max, y_crop_max): - 左上角x_crop_min在区间[0, min_x]中随机选择(若min_x<0则取0) - 左上角y_crop_min在区间[0, min_y]中随机选择 - 右下角x_crop_max在区间[max_x, 原图宽度]中随机选择 - 右下角y_crop_max在区间[max_y, 原图高度]中随机选择 这样,裁剪区域[ x_crop_min, y_crop_min, x_crop_max, y_crop_max ]就包含了整个最小外接矩形(即所有安全框)。 5. 裁剪图像:image_cropped = image[y_crop_min:y_crop_max, x_crop_min:x_crop_max] 6. 调整边界框坐标: 对于每个原始边界框(bbox: [x_min, y_min, x_max, y_max]): 新x_min = max(x_min, x_crop_min) - x_crop_min 新y_min = max(y_min, y_crop_min) - y_crop_min 新x_max = min(x_max, x_crop_max) - x_crop_min 新y_max = min(y_max, y_crop_max) - y_crop_min 如果新边界框的宽度或高度小于等于0,则丢弃该边界框(在目标检测中,通常要求边界框非负且有一定大小,否则视为无效)。 7. 返回裁剪后的图像和调整后的边界框。 注意:上面的步骤3和4中,我们选择裁剪区域的方法是:确保裁剪区域包含整个最小外接矩形。但是,在实际实现中,可能还会限制裁剪区域的最小尺寸(比如至少为原图的1/10等),以避免裁剪区域小。 另外,如果图像中没有边界框,则无法计算安全框,此时有两种处理方式: - 跳过该变换(即不裁剪)? - 或者进行普通的随机裁剪(不保证边界框安全)? 在Albumentations的BBoxSafeRandomCrop中,如果没有边界框,则会回退到普通的随机裁剪(或者跳过?需要查看具体实现)。但根据变换的目的,如果没有边界框,那么就不需要保证边界框安全,可以直接随机裁剪。 因此,我们可以这样概括: if 有边界框: 按照上述步骤进行安全裁剪 else: 进行普通的随机裁剪(按照给定的裁剪尺寸或范围) 然而,在给定的函数调用中,并没有指定裁剪的尺寸,所以通常这个变换会随机选择裁剪区域的大小(在满足包含安全框的前提下,其大小由随机选择的左上角和右下角决定)。因此,裁剪后的图像尺寸是不固定的。 另外,为了控制裁剪区域的大小,实际实现中可能还会设定最小裁剪比例或最大裁剪比例,以避免裁剪区域过大或过小。 最后,总结该变换的核心:通过侵蚀边界框得到安全框,然后确保裁剪区域包含所有安全框,从而保证裁剪后每个边界框的中心部分(安全框)都被保留。 </think>### BBoxSafeRandomCrop 原理详解 `BBoxSafeRandomCrop(erosion_rate=0.2, p=0.1)` 是一种面向目标检测任务的数据增强技术,核心目标是在随机裁剪图像时**确保边界框(Bounding Box)内的目标物体不会被裁切丢失**。其工作原理可分为以下关键步骤: #### 1. **边界框侵蚀(Bounding Box Erosion)** - **目的**:创建安全缓冲区 - **操作**:对每个边界框应用侵蚀率(`erosion_rate=0.2`) ```math \begin{aligned} \text{侵蚀后宽度} &= w \times (1 - 2 \times 0.2) = 0.6w \\ \text{侵蚀后高度} &= h \times (1 - 2 \times 0.2) = 0.6h \end{aligned} ``` - **效果**: <div align=center> ![BBox Erosion](https://via.placeholder.com/400x200?text=原始框→安全框) *边界框向内收缩20%,保留60%核心区域作为安全框* </div> #### 2. **安全裁剪约束** - **关键限制**:随机裁剪区域必须**完全包含所有侵蚀后的安全框** - **数学约束**: ```math \begin{cases} x_{\text{crop}} \leq \min(x_{\text{safe}}) \\ y_{\text{crop}} \leq \min(y_{\text{safe}}) \\ x_{\text{crop}} + w_{\text{crop}} \geq \max(x_{\text{safe}} + w_{\text{safe}}) \\ y_{\text{crop}} + h_{\text{crop}} \geq \max(y_{\text{safe}} + h_{\text{safe}}) \end{cases} ``` - **效果**:裁剪区域必然覆盖所有目标的中心安全区域 #### 3. **裁剪与坐标调整** - **裁剪执行**:在满足约束条件下随机选择裁剪位置和尺寸 - **坐标变换**: ```math \begin{aligned} x_{\text{new}} &= x_{\text{orig}} - x_{\text{crop}} \\ y_{\text{new}} &= y_{\text{orig}} - y_{\text{crop}} \end{aligned} ``` - **边界框修正**:裁剪后自动调整边界框坐标至新坐标系 #### 4. **概率控制(p=0.1)** - 仅10%的概率启用该增强,90%概率返回原图 - 避免过度增强导致数据偏差 #### 实际效果示例 ```python 原图尺寸:(640, 480) 边界框:[120,80,200,200] # [x_min,y_min,x_max,y_max] 安全框计算:(侵蚀率0.2) 宽度 = 80 → 安全宽度=80*0.6=48 中心点=(160,140) 安全框:[160-24, 140-24, 160+24, 140+24] = [136,116,184,164] 随机裁剪区域: 必须满足:x_crop≤136, y_crop≤116, x_crop+w_crop≥184, y_crop+h_crop≥164 可能的裁剪:[100,100, 300, 300] → 符合约束 ``` ### 设计优势 1. **目标完整性**:通过安全框机制保证目标至少保留60%可见区域 2. **多样性增强**:随机裁剪位置/尺寸创造丰富训练样本 3. **兼容性**:支持多目标场景(需覆盖所有安全框) 4. **参数可控**:`erosion_rate`平衡安全性与增强强度 > ⚠️ **注意**:当多个边界框分散时,约束可能导致裁剪区域较大。此时可通过: > - 降低`erosion_rate` > - 结合缩放操作 > - 限制最大裁剪区域尺寸 --- ### 相关问题 1. **如何选择最优的`erosion_rate`值?不同任务(如小目标检测)是否有特殊调整策略?** 2. **当图像中存在多个分散目标时,如何避免裁剪区域过大导致的增强效果弱化?** 3. **该增强方法在YOLO/Faster R-CNN等主流检测模型中的实际效果对比如何?** 4. **能否与其他增强方法(如MixUp/Mosaic)结合使用?是否存在冲突风险?** [^1]: 参考图像数据增强标准库Albumentations的实现逻辑
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值