数据结构总结1(火车进栈/兔子与兔子/括号画家/Editor/邻值查找/最大子序和/前缀统计/Phone List/The XOR Largest Pair)

问题 A: 火车进栈

题目描述

这里有n列火车将要进站再出站……
但是,每列火车只有1节—那就是车头……
描述
有n列火车按1到n的顺序从东方左转进站,这个车站是南北方向的,它虽然无限长,只可惜是一个死胡同,而且站台只有一条股道,火车只能倒着从西方出去,而且每列火车必须进站,先进后出。
(某生:不就是个栈吗?每次可以让右侧头火车进栈,或者让栈顶火车出站?
老师:闭嘴!)
就像这样:
出站<——- <——进站
|车|
|站|
|__|
现在请你按《字典序》输出前20种可能的出栈方案。

输入

一个整数 n<=20

输出

按照《字典序》输出前20种答案,每行一种,不要空格

样例输入 Copy

3

样例输出 Copy

123
132
213
231
321

思路
依题意可知,火车只有入栈和出栈两个操作,且所有火车都需要进行这两种操作,使用STL中的stack来模拟该操作。使用visit[ ]数组来判断火车是否已经入栈,注意只有当第i-1个火车入栈后,第i个火车才能入栈。使用dfs的写法即可完成此题。

#include <iostream>
#include <stack>
#include <vector>
using namespace std;

int n;
bool visit[25];///已经如果栈的标志
stack<int> s;
vector<int>ans;
int cnt=0;
void solve()
{
    if(cnt>=20) return;
    if(ans.size()==n)///搜索边界,输出答案
    {
        for(int i=0;i<n;i++)cout<<ans[i];
        cout<<endl;
        cnt++;
        return;
    }
    if(!s.empty())///栈内不为空,可以出栈
    {
        int x=s.top();
        ///出栈
        ans.push_back(x);
        s.pop();
        solve();///栈顶出栈后,向下一层搜索
        ///还原状态
        ans.pop_back();
        s.push(x);
    }
    for(int i=1;i<=n;i++)
    {
        if(!visit[i]&&visit[i-1])///第i辆未入栈,i-1辆已经入过栈
        {
            visit[i]=true;
            s.push(i);
            solve();
            ///状态恢复,回溯
            visit[i]=false;
            s.pop();
        }
    }
    return;
}

int main()
{
    visit[0]=true;
    cin>>n;
    solve();
    return 0;
}

问题 I: 兔子与兔子

题目描述

很久很久以前,森林里住着一群兔子。有一天,兔子们想要研究自己的 DNA 序列。我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母),然后我们每次选择两个区间,询问如果用两个区间里的 DNA 序列分别生产出来两只兔子,这两个兔子是否一模一样。注意两个兔子一模一样只可能是他们的 DNA 序列一模一样。

输入

第一行一个 DNA 字符串 S。
接下来一个数字 m,表示 m 次询问。
接下来 m 行,每行四个数字 l1, r1, l2, r2,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。
其中 1 ≤ length(S), m ≤ 1000000

输出

对于每次询问,输出一行表示结果。如果两只兔子完全相同输出 Yes,否则输出 No(注意大小写)

样例输入 Copy

aabbaabb
3
1 3 5 7
1 3 6 8
1 2 1 2

样例输出 Copy

Yes
No
Yes

思路
字符串hash求解即可
字符串hash函数:
对于字符串C,使用质数b,及模数h来计算hash函数
H( C )=[ c1 * bm + c2 * b(m-1) + . . . + cn*b1 ] mod h
可以理解为字符串讲C可以转化为一个m位b进制的数
注意
实际用32/64位无符号整数来计算哈希值,这样的话,当哈希值溢出时,系统会自动对h=232 / h=264取模。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

char s[1000005];
unsigned long long sum[1000005],bit[1000005]={1};///注意bit[1]=131
///用32/64位无符号整数来计算哈希值,当哈希值溢出时,系统会自动对h=2^32 / h=2^64取模。
int main()
{
    scanf("%s",s+1);
    int len=strlen(s+1);
    for(int i=1;i<=len;i++)
    {
        sum[i]=sum[i-1]*131+s[i]-'a'+1;
        bit[i]=bit[i-1]*131;
    }
    int n;
    cin>>n;
    while(n--)
    {
        int l1,r1,l2,r2;
        scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
        if(sum[r1]-sum[l1-1]*bit[r1-l1+1]==sum[r2]-sum[l2-1]*bit[r2-l2+1])
        ///注意乘以bit[r1-l1+1],将两个数转化位位数相同
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

问题 S: 括号画家

题目描述

Candela是一名漫画家,她有一个奇特的爱好,就是在纸上画括号。这一天,刚刚起床的Candela画了一排括号序列,其中包含小括号( )、中括号[ ]和大括号{ },总长度为N。这排随意绘制的括号序列显得杂乱无章,于是Candela定义了什么样的括号序列是美观的:
(1) 空的括号序列是美观的;
(2) 若括号序列A是美观的,则括号序列 (A)、[A]、{A} 也是美观的;
(3) 若括号序列A、B都是美观的,则括号序列AB也是美观的。
例如 (){} 是美观的括号序列,而 )({)[}]( 则不是。
现在Candela想在她绘制的括号序列中,找出其中连续的一段,满足这段子序列是美观的,并且长度尽量大。你能帮帮她吗?S

输入

一个由括号组成的字符串。

输出

一个整数,表示最长的美观的子段的长度。

样例输入 Copy

({({(({()}})}{())})})[){{{([)()((()]]}])[{)]}{[}{)

样例输出 Copy

4

思路
1.首先读题知道如果一个左括号c1,向右查询得到的第一个右括号c2与c1匹配的话,那么这两个括号是合法的,否则非法。
2.那么可以使用栈stack来模拟括号匹配:
1)为左括号则入栈
2)否则判断右括号是否和栈顶的左括号匹配,若匹配则计数器cnt+=2,更新答案ans,且弹栈,若不匹配则cnt=0,清栈。

#include <iostream>
#include <stack>
#include <cstdio>
#include <cstring>
using namespace std;
stack<char> sta;
char s[100005];
bool judge(char a,char b)
{
    if(a=='('&&b==')') return true;
    if(a=='['&&b==']') return true;
    if(a=='{'&&b=='}') return true;
    return false;
}
int main()
{
    scanf("%s",s);
    int ans=0,cnt=0;
    for(int i=0;i<strlen(s);i++)
    {
        if(s[i]=='('||s[i]=='['||s[i]=='{')
            sta.push(s[i]);
        else
        {
            char c='a';
            if(!sta.empty())c=sta.top();
            if(judge(c,s[i]))
            {
                cnt+=2;
                ans=max(cnt,ans);
                sta.pop();
            }
            else
            {
                cnt=0;
                while(!sta.empty()) sta.pop();
            }
        }
    }
    cout << ans << endl;
    return 0;
}


问题 C: Editor

题目描述

You are going to implement the most powerful editor for integer sequences.
The sequence is empty when the editor is initialized.
There are 5 types of instructions.

I x Insert x after the cursor.
D Delete the element before the cursor.
L Move the cursor left unless it has already been at the begin.
R Move the cursor right unless it has already been at the end.
Q k Suppose that the current sequence BEFORE the cursor is {a1,a2,…,an}.Find max1≤i≤k Si where Si=a1+a2+…+ai.

输入

The input file consists of multiple test cases.For eache test case:
The first line contains an integer Q,which is the number of instructions.The next Q lines contain an instruction as described above。
(1≤Q≤106,|x|≤103 for I instruction,1≤k≤n for Q instruction)

输出

For eache Q instruction,output the desired value.

样例输入 Copy

8
I 2
I -1
I 1
Q 3
L
D
R
Q 2

样例输出 Copy

2
3

思路
使用对顶栈,用L来表示光标左边的数据,R表示光标右边的数据,LR的一弹栈一入栈来模拟光标移动。并且使用数组num来维护前 i 项和,数组maxn来维护前 i 项和的最大值

#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
using namespace std;

///通过LR的弹栈和入栈操作模拟光标的移动
stack<int>L,R;///对顶堆,L为光标左边的堆,R为光标右边的
vector<int>num,maxn;///num为前i项和,maxn为前i项和中的最大值
int n,x;
char op;

int main()
{
    num.push_back(0);///初始化为0
    maxn.push_back(-0xffffff);///初始化为最小值,以为数列中有负值
    cin>>n;
    getchar();
    while(n--)
    {
        cin>>op;
        if(op=='I')///插入操作,则L入栈,更新前n项和及其最大值
        {
            cin>>x;
            L.push(x);
            num.push_back(num[num.size()-1]+x);
            maxn.push_back(max(num[num.size()-1],maxn[maxn.size()-1]));
        }
        if(op=='D')///删除操作,L弹栈,前n项和也更新弹出最后一项
        {
            if(!L.empty())
            {
                L.pop();
                num.pop_back();
                maxn.pop_back();
            }
        }
        if(op=='L')///光标左移,则L弹栈,R入栈
        {
            if(!L.empty())///注意要L非空
            {
                R.push(L.top());
                L.pop();
                num.pop_back();///前n项和弹出最后一项
                maxn.pop_back();
            }
        }
        if(op=='R')///光标右移动,同上
        {
            if(!R.empty())
            {
                L.push(R.top());
                ///前n项和更新
                num.push_back(R.top()+num[num.size()-1]);
                maxn.push_back(max(num[num.size()-1],maxn[maxn.size()-1]));
                R.pop();
            }
        }
        if(op=='Q')///询问
        {
            scanf("%d",&x);
            cout<<maxn[x]<<'\n';
        }
    }
    return 0;
}


问题 H: 邻值查找

题目描述

给定一个长度为 n 的序列 A,A 中的数各不相同。对于 A 中的每一个数 Ai,求:
min(1≤j<i) ⁡|Ai-Aj|
以及令上式取到最小值的 j(记为 Pi)。若最小值点不唯一,则选择使 Aj 较小的那个。

输入

第一行一个整数n,第二行n个数A_1~A_n。

输出

n-1行,每行2个用空格隔开的整数。分别表示当i取2~n时,对应的 min(1≤j<i) ⁡|A_i-A_j| 和 P_i 的值。

样例输入 Copy

3
1 5 3

样例输出 Copy

4 1
2 1

提示

对于30%的数据: n<=100
对于70%的数据: n<=10^4
对于100%的数据: n<=10^5, |A_i|<=10^9

思路
1)数据结构的选择
由题意可以知道后面加入的数x,要去找到前面和他绝对值差值最小的数y(y有两种情况,y>x,y<x)然后插入x。这个插入的过程类似与平衡二叉树的建树过程,所以可以使用平衡二叉树来进行数据的维护。然而c++中STL的set就是使用红黑树(自平衡查找二叉树)写的,使用set进行数据维护即可,并且set有lower_bound(x)函数来查找<x的最大的数据(当然要重载<)。
2)每次插入前,去找到当前这个数字最接近的值的前驱和后驱,比较前驱和后驱,找到最小的j,
如果找不到大于等于这个数字,能么需要判断end()(注意stl中全部都是以左闭右开的形式来保存的),去直接输出end()-1,同理如果是begin(),直接输出begin()+1

#include <iostream>
#include <set>
#include <cstdio>
#include <cmath>
using namespace std;

struct node
{
    int num,id;
    bool operator<(const node &a) const
    {
        return num<a.num;
    }
};
set<node>s;

int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        int tmp;
        scanf("%d",&tmp);
        if(i==1) 
            {s.insert(node{tmp,i});continue;}
        set<node>::iterator right=s.lower_bound(node{tmp,0}),left=right;left--;
        if(right==s.end())
            printf("%d %d\n",tmp-left->num,left->id);
        else if(right==s.begin())
            printf("%d %d\n",right->num-tmp,right->id);
        else if((tmp-left->num)<=(right->num-tmp))
            printf("%d %d\n",tmp-left->num,left->id);
        else
            printf("%d %d\n",right->num-tmp,right->id);
        s.insert(node{tmp,i});
    }
    return 0;
}


问题 E: 最大子序和

题目描述

输入一个长度为n的整数序列,从中找出一段不超过m的连续子序列,使得整个序列的和最大。

例如 1,-3,5,1,-2,3

当m=4时,S=5+1-2+3=7
当m=2或m=3时,S=5+1=6

输入

第一行两个数n,m(n,m<=300000)
第二行有n个数,要求在n个数找到最大子序和

输出

一个数,数出他们的最大子序和

样例输入 Copy

6 4
1 -3 5 1 -2 3

样例输出 Copy

7

使用的数据结构
单调队列

单调递增队列的创建过程(队首到队尾单调递增):
若队列为空,将元素x从队尾入队
若队列不为空,将比元素x大的元素都从队尾弹出,然后把元素x入队
若队列不为空且元素x大于队尾,则直接从队尾把元素x入队

**注意**:单调递增队列维护的是区间最小值,而单调递减队列维护的是最区间大值
两个队列都是对首维护的是最小值/最大值

值得一提的是:单调栈的创建过程同单调队列,其出栈的序列是单调的

注意
单调队列的单调不一定是数字大小顺序上的单调,可以将判断顺序的依据重载,根据题目所需重新定义排序规则

思路
使用单调队列求解(用双端队列实现,因为还需要判断区间长度是否大于m,队首队尾都要访问,且都要可以出队)
求解过程:
1)求出前缀和以便求出区间和
2)因为要判断区间长度是否大于m,所以单调递增队列储存的是下标,维护的是区间[i-m,i]最小值的序号q.front(),那么sum[i]-sum[q.front()]即为区间[i-m,i]的最大值。

#include <iostream>
#include <deque>
using namespace std;

deque<int> q;
long long sum[300005];
long long maxn;

void solve(int n,int m)
{
    maxn=sum[1];
    q.push_back(1);
    for(int i=2;i<=n;i++)
    {
        while(!q.empty()&&i-q.front()>m)///去除区间长度大于m的队尾元素
            q.pop_front();
        maxn=max(maxn,sum[i]-sum[q.front()]);///更新最大值
        while(!q.empty()&&sum[i]<sum[q.back()])///单调队列更新
            q.pop_back();
        q.push_back(i);///入队
    }
}

int main()
{
    int n,m;cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int x;cin>>x;
        sum[i]=sum[i-1]+x;
    }
    solve(n,m);
    cout<<maxn<<endl;
    return 0;
}


问题L 前缀统计

题目描述:
给定N个字符串S1,S2…SN,接下来进行M次询问,每次询问给定一个字符串T,求S1~SN中有多少个字符串是T的前缀。

输入字符串的总长度不超过106,仅包含小写字母。

输入格式

第一行输入两个整数N,M。接下来N行每行输入一个字符串Si。接下来M行每行一个字符串T用以询问。

输出格式

对于每个询问,输出一个整数表示答案。每个答案占一行。

输入样例:

3 2
ab
bc
abc
abc
efg

输出样例:

2
0

思路
裸的字典树(26叉树)模板,参考博客

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

struct node
{
    int sum;
    node* c[26];
    node()
    {
    	memset(c,NULL,sizeof(c));
    	sum=0;
    }
}* root=new node;
int n,m;
char str[1000005];

void Insert(const char *s)///trie树插入操作
{
    node *e=root;
    while(*s)
    {
        if(!e->c[*s-'a'])
            e->c[*s-'a']=new node;
        e=e->c[*s++ -'a'];
    }
    ++(e->sum);
}

int query(char *s)///trie树查询操作
{
    int res=0;
    node *e=root;
    while(*s&&e)
    {
        res+=e->sum;
        e=e->c[*s++ -'a'];
    }
    if(e)///注意*s=='\0'时,e可能!=null
        res+=e->sum;
    return res;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",str);
        Insert(str);
    }
    long long ans=0;
    for(int i=1;i<=m;i++)
    {
        scanf("%s",str);
        cout<<query(str)<<'\n';
    }
    return 0;
}

问题 AB: 【Trie 字典树】Phone List

题目描述

Given a list of phone numbers, determine if it is consistent in the sense that no number is the prefix of another. Let’s say the phone catalogue listed these numbers:
• Emergency 911
• Alice 97 625 999
• Bob 91 12 54 26
In this case, it’s not possible to call Bob, because the central would direct your call to the emergency line as soon as you had dialled the first three digits of Bob’s phone number. So this list would not be consistent.

输入

The first line of input gives a single integer, 1 ≤ t ≤ 40, the number of test cases. Each test case starts with n, the number of phone numbers, on a separate line, 1 ≤ n ≤ 10000.
Then follows n lines with one unique phone number on each line. A phone number is a sequence of at most ten digits.

输出

For each test case, output “YES” if the list is consistent, or “NO” otherwise.

样例输入 Copy

2
3
911
97625999
91125426
5
113
12340
123440
12345
98346

样例输出 Copy

NO
YES

思路
先进行插入操作,建树,然后遍历所有的字符串str[i],在树上找到该字符串str[i]的最后一个节点,查询其是否有子节点,若有则输出NO,若遍历后都没有则输出YES。注意每组操作结束后记得将树删除。
注意
节点的构造函数记得写,还有题目没给出每个字符串的长度所有使用动态的字符串string。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <stack>
using namespace std;

string str[10005];///没给出具体长度,使用string
struct node
{
    node *c[10];
    node()
    {
        memset(c,NULL,sizeof(c));///不能忘,否则会出错
    }
}* root;

void Insert(string s)
{
    node *e=root;
    int len=s.size();
    for(int i=0;i<len;i++)
    {
        if(!e->c[s[i]-'0'])
            e->c[s[i]-'0']=new node;
        e=e->c[s[i]-'0'];
    }
}

void Delete(node *e)
{
    for(int i=0;i<10;i++)
        if(e->c[i])
            Delete(e->c[i]);
    if(e) delete e;
}

bool query(string s)
{
    node *e=root;
    int len=s.size();
    for(int i=0;i<len;i++)
        e=e->c[s[i]-'0'];
    for(int i=0;i<=9;i++)
        if(e->c[i]) return false;
    return true;
}

int main()
{
    int t;cin>>t;
    while(t--)
    {
        root=new node;
        int n;cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>str[i];
            Insert(str[i]);
        }
        int sign=0;
        for(int i=1;i<=n;i++)
        {
            if(!query(str[i]))
            {
                sign=1;
                break;
            }
        }
        if(sign) cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
        Delete(root);
    }
    return 0;
}


问题 M: 【Trie 字典树】The XOR Largest Pair

题目描述

在给定的N个整数A1,A2……AN中选出两个进行xor运算,得到的结果最大是多少?

输入

第一行一个整数N,第二行N个整数A1~AN。

输出

一个整数表示答案。

样例输入 Copy

3
1 2 3

样例输出 Copy

3

提示

对于100%的数据: N<=105, 0<=Ai<231

思路
将数按二进制表示从高位到低位插入到字典树中(这样可以保证数查询时尽量大,因为高位异或得到的1的权值大于低位异或得到的1的权值),然后每个数查询时往与当前位相反的树的分支查询。如:a[1…4]=1001,a[1]查询时往树0的分支走。

代码1
使用change()函数将数转化为2进制,位数不够前面补零

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

long long a[100005];
struct node///字典树节点
{
    long long num;
    node* e[2];
    node()
    {
        memset(e,0,sizeof(e));
        num=-1;
    }
}*root =new node;

///将一个数转化为2进制字符串
void change(long long x,char p[])///要返回一个字符串,可以直接
{                    ///用字符串做参数,在函数里面改变其值,返回的值也改变了
    int cnt=0;       ///char p[]和char *p效果一样
    while(x)
    {
        if(x&1) p[cnt++]='1';
        else p[cnt++]='0';
        x/=2;
    }
    for(int i=cnt;i<=31;i++)
        p[i]='0';
    reverse(p,p+31);
}

void Insert(long long x)///插入函数
{
    char c[35]="\0";
    change(x,c);
    node *o=root;
    for(int i=0;c[i];i++)
    {
        if(!o->e[c[i]-'0'])  o->e[c[i]-'0']=new node;
        o=o->e[c[i]-'0'];
    }
    o->num=x;
}

long long query(long long x)///查询函数
{
    char c[35]="\0";
    change(x,c);
    node *o=root;
    for(int i=0;c[i]&&o;i++)
    {
        int n=c[i]-'0';
        if(o->e[!n])  o=o->e[!n];///往与其相反的方向查询
        else  o=o->e[n];		 ///往与其相同的方向查询
    }
    return x^o->num;
}

int main()
{
    int n;cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        Insert(a[i]);
    }
    long long maxn=0;
    for(int i=1;i<=n;i++)  maxn=max(maxn,query(a[i]));
    cout<<maxn<<endl;
    return 0;
}

代码2
其实不需要使用change()函数,直接使用位移运算符<<即可,简化后的代码

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

long long a[100005];
struct node
{
    long long num;
    node* e[2];
    node()
    {
        memset(e,0,sizeof(e));
        num=-1;
    }
}*root =new node;

void Insert(long long x,node *o=root)
{
    for(int i=30;i>=0;i--)
    {
        int bit=x>>i&1;///注意要&1,否则不是最后一位
        if(!o->e[bit])  o->e[bit]=new node;
        o=o->e[bit];
    }
    o->num=x;
}

long long query(long long x,node *o=root)
{
    for(int i=30;i>=0;i--)
    {
        int n=x>>i&1;
        if(o->e[!n])  o=o->e[!n];
        else  o=o->e[n];
    }
    return x^o->num;
}

int main()
{
    int n;cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        Insert(a[i]);
    }
    long long maxn=0;
    for(int i=1;i<=n;i++)  maxn=max(maxn,query(a[i]));
    cout<<maxn<<endl;
    return 0;
}

代码3
使用数组实现
数组实现的解析可以参考:博客

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

int trie[100000*31+10][2];///节点数组,最多100000*31个节点
int tot=0;///节点数

void Insert(int x)
{
    int e=0;///根节点
    for(int i=30;i>=0;i--)
    {
        int bit=x>>i&1;///获取当前位的01值
        if(!trie[e][bit]) trie[e][bit]=++tot;///建立节点
        e=trie[e][bit];///向建立好的节点移动
    }
}

long query(int x)
{
    int e=0;
    long ans=0;///x和前面所有数异或的最大值
    for(int i=30;i>=0;i--)
    {
        int bit=x>>i&1;///获取当前位的01值
        if(trie[e][!bit])///向着与当前位的值相反方向查询
        {
            e=trie[e][!bit];///节点移动
            ans|=(1<<i);///当前节点和x的第i位异或位1,则ans第i位为1
        }
        else e=trie[e][bit];
    }
    return ans;
}

int main()
{
    int n;cin>>n;
    long maxn=0;
    while(n--)
    {
        int x; cin>>x;
        Insert(x);///插入
        maxn=max(maxn,query(x));///可以直接查询并更新最大值
    }
    cout<<maxn<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值