牛客寒假训练题目复习

一、
1.maki和tree
链接
题目描述
有一天,maki拿到了一颗树。所谓树,即没有自环、重边和回路的无向连通图。
这个树有 个顶点, 条边。每个顶点被染成了白色或者黑色。
maki想知道,取两个不同的点,它们的简单路径上有且仅有一个黑色点的取法有多少?
注:
①树上两点简单路径指连接两点的最短路。
② <p,q>和<q,p> 的取法视为同一种。

第一行一个正整数 n。代表顶点数量。(1<=n<=100000)
第二行是一个仅由字符’B’和’W’组成的字符串。第 i个字符是B代表第 i个点是黑色,W代表第 i个点是白色。
接下来的 n-1行,每行两个正整数 x,y ,代表 x点和y 点有一条边相连

思路:dfs。先算出每一个白色联通块中有几个白色,将其全部赋值为总数,这样没找到一个黑色就可以直接算。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100005;
struct node{
	int ne,to;
}e[N*2];
int fir[N],n,t,f[N],num[N];
vector<int> vec;
char s[N];
void add(int u,int v){
	t++;
	e[t].to=v;
	e[t].ne=fir[u];
	fir[u]=t;
}
void dfs(int x){
	for(int i=fir[x];i!=-1;i=e[i].ne){
		int v=e[i].to;
		if(f[v]||s[v]=='B')continue;
		f[v]=1;
		vec.push_back(v);
		dfs(v);
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		cin>>s[i];
	}
	memset(fir,-1,sizeof(fir));
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v);
		add(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='W'&&!f[i]){
			vec.clear();
			vec.push_back(i);
			f[i]=1;
			dfs(i);
			for(int j=0;j<vec.size();j++){
				num[vec[j]]=vec.size();
			}
		}
	}
	ll ans=0;
	for(int i=1;i<=n;i++){
		if(s[i]=='B'){
			ll sum=0;
			for(int j=fir[i];j!=-1;j=e[j].ne){
				//cout<<"pp"<<endl;
				int v=e[j].to;
				ans+=num[v];
				ans+=sum*num[v];
				sum+=num[v];
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}

2.nozomi和字符串

题目描述
nozomi看到eli在字符串的“花园”里迷路了,决定也去研究字符串问题。
她想到了这样一个问题:
对于一个 “01”串而言,每次操作可以把0 字符改为 1 字符,或者把 1 字符改为 0 字符。所谓“01”串,即只含字符 0 和字符 1 的字符串。
nozomi有最多 次操作的机会。她想在操作之后找出一个尽可能长的连续子串,这个子串上的所有字符都相同。
nozomi想问问聪明的你,这个子串的长度最大值是多少?
注: 次操作机会可以不全部用完。
如果想知道连续子串的说明,可以去问问eli,nozomi不想再讲一遍。

思路1:二分长度,分(1,0)和(0,1)两种情况,取最大值

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100005;
int n,k;
string s;
bool check1(int x){
	int l=0,r=x-1;
	string c=s;
	int sum=0;
	for(int i=l;i<=r;i++){
		if(c[i]=='1'){
			sum++;
		}
	}
	int cnt=sum;
	while(1){
		r++;
		if(r==n)break;
		if(c[l]=='1')sum--;
		l++;
		if(c[r]=='1')sum++;
		//if(c[l]=='1')sum++;
		cnt=min(cnt,sum);
	}
	return cnt<=k;
}
bool check2(int x){
	int l=0,r=x-1;
	string c=s;
	int sum=0;
	for(int i=l;i<=r;i++){
		if(c[i]=='0'){
			sum++;
		}
	}
	int cnt=sum;
	while(1){
		r++;
		if(r==n)break;
		if(c[l]=='0')sum--;
		l++;
		if(c[r]=='0')sum++;
		//if(c[l]=='0')sum++;
		cnt=min(cnt,sum);
	}
	return cnt<=k;
}
int main(){
	scanf("%d%d",&n,&k);
	cin>>s;
	int l=1,r=n;
	while(l<r){
		int mid=(l+r+1)>>1;
		if(check1(mid))l=mid;
		else r=mid-1;
	}
	int ans=0;
	//cout<<l<<"kk"<<endl;
	ans=max(ans,l);
	l=1,r=n;
	while(l<r){
		int mid=(l+r+1)>>1;
		if(check2(mid))l=mid;
		else r=mid-1;
	}
	ans=max(ans,l);
	//cout<<l<<"kk"<<endl;
	cout<<ans<<endl;
	return 0;
}

思路2:尺取
当满足k时变换l,每次取最大值

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
int n,k;
string s;
int cz(char a,char b){
    int l=0,r=0,sum=0,ans=0;
    for(int i=0;i<n;i++){
        if(s[i]==a){
            if(sum<k){
                sum++;
                r++;
            }
            else{
                while(l<=r&&s[l]!=a)l++;
                l++;
                r++;
            }
        }
        else r++;
        ans=max(ans,r-l);
    }
    return ans;
}
int main(){
    scanf("%d%d",&n,&k);
    cin>>s;
    int ans=max(cz('0','1'),cz('1','0'));
    cout<<ans<<endl;
    return 0;
}

3.nico和niconiconi
链接
nico平时最喜欢说的口头禅是niconiconi~。
有一天nico在逛著名弹幕网站"niconico"的时候惊异的发现,n站上居然有很多她的鬼畜视频。其中有一个名为《让nico为你洗脑》的视频吸引了她的注意。
她点进去一看,就被洗脑了:“niconicoh0niconico*^vvniconicoG(vniconiconiconiconiconicoG(vniconico…”
弹幕中刚开始有很多“nico1 nico2”等计数菌,但到后面基本上都是“计数菌阵亡”的弹幕了。
nico也想当一回计数菌。她认为:“nico” 计 a分,“niconi” 计b 分,“niconiconi” 计 c分。
她拿到了一个长度为 的字符串,请帮她算出最大计数分数。
注:已被计数过的字符不能重复计数!如"niconico"要么当作"nico"+“nico"计a+a分,要么当作"niconi”+"co"计 b分。

思路:简单01背包变形

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
const int N=300005;
char s[N];
ll n,a,b,c;
ll dp[N];
int main(){
    scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
    for(int i=1;i<=n;i++){
        cin>>s[i];
    }
    for(int i=1;i<=n;i++){
        dp[i]=dp[i-1];
        if(i>=4){
            if(s[i]=='o'&&s[i-1]=='c'&&s[i-2]=='i'&&s[i-3]=='n'){
                dp[i]=max(dp[i],dp[i-4]+a);
            }
        }
        if(i>=6){
            if(s[i]=='i'&&s[i-1]=='n'&&s[i-2]=='o'&&s[i-3]=='c'&&s[i-4]=='i'&&s[i-5]=='n'){
                dp[i]=max(dp[i],dp[i-6]+b);
            }
        }
        if(i>=10){
            if(s[i]=='i'&&s[i-1]=='n'&&s[i-2]=='o'&&s[i-3]=='c'&&s[i-4]=='i'&&s[i-5]=='n'&&s[i-6]=='o'&&s[i-7]=='c'&&s[i-8]=='i'&&s[i-9]=='n'){
                dp[i]=max(dp[i],dp[i-10]+c);
            }
        }
    }
    cout<<dp[n]<<endl;
    return 0;
}

二、
1.算概率
链接
逆元情况下给的概率可以直接算。
dp。
dp[i][j]表示前i个数有j个正确的概率。
初始化每一个dp[i][0].

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=2005;
int n;
ll a[N],f[N][N]; 
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	f[0][0]=1;
	for(int i=1;i<=n;i++){
		f[i][0]=(f[i-1][0]*(1-a[i]+mod)%mod)%mod;
		for(int j=1;j<=i;j++){
			f[i][j]=((f[i-1][j]*(1-a[i]+mod)%mod)%mod+f[i-1][j-1]*a[i]%mod)%mod;
		}
	}
	for(int i=0;i<=n;i++){
		if(i==n)printf("%lld\n",f[n][i]);
		else printf("%lld ",f[n][i]);
	}
	return 0;
} 

2.拿物品
链接
贪心
每个人拿走一个物品,得到的利益都是a+b,比如牛牛他得到了a也让可乐损失了b,所以贪心排个序即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=200005;
int n;
struct node{
	ll a,b,s,id;
}p[N];
ll ans1[N],ans2[N];
bool cmp(node x,node y){
	return x.s>y.s;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&p[i].a);
		p[i].id=i;
	}
	for(int i=1;i<=n;i++){
		scanf("%lld",&p[i].b);
		p[i].s=p[i].a+p[i].b;
	}
	sort(p+1,p+1+n,cmp);
	int cnt1=0,cnt2=0;
	for(int i=1;i<=n;i++){
		if(i&1)ans1[++cnt1]=p[i].id;
		else ans2[++cnt2]=p[i].id;
	}
	for(int i=1;i<=cnt1;i++){
		if(i==cnt1)printf("%lld\n",ans1[i]);
		else printf("%lld ",ans1[i]);
	}
	for(int i=1;i<=cnt2;i++){
		if(i==cnt2)printf("%lld\n",ans2[i]);
		else printf("%lld ",ans2[i]);
	}
	return 0;
} 

3.施魔法
链接
简单dp
两种选择,一是连接在上一个后面,另一个是开辟新的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=300005;
const int inf=0x3f3f3f3f;
int n,k;
ll a[N],f[N];
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
        f[i]=inf;
	}
	sort(a+1,a+1+n);
	f[k]=a[k]-a[1];
	for(int i=k+1;i<=n;i++){
		f[i]=min(f[i-1]+a[i]-a[i-1],f[i-k]+a[i]-a[i-k+1]);
	}
	cout<<f[n]<<endl;
	return 0;
}

4.建通道
链接
二进制
具题意,两个相同的点的路费为0,所以要先去重,当找到一个01对的时候意味着找到两个点之间最短的路费,后面的这个位置是1的连到01对的0上,是0的连到1上,所以这(sm-1)条边全部是最短路费。
这里找01对不用循环套循环(会t),只需要看看0或者1的数目是否为0或者是sm。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=200005;
int n,k;
ll v[N];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&v[i]);
	}
	sort(v+1,v+1+n);
	int sm=unique(v+1,v+1+n)-(v+1);
	if(sm==1){
		printf("0\n");
		return 0;
	}

	for(int i=0;i<30;i++){
		int sum=0;
		for(int j=1;j<=sm;j++){
			if(v[j]>>i&1)sum++;
		}
		if(sum>0&&sum<sm){
			ll res=((ll)sm-1ll)*(1ll<<i);
			printf("%lld\n",res);
			break;
		}
	}
	
	return 0; 
}

三、
1、牛牛的Link Power II
链接
线段树
思路:如何在前后两个区域建立联系,不妨模拟一下,首先我们知道两点之间的距离是pos2-pos1,另一边有几个数代表这边的数要贡献几次。所以线段树中记录一块区域的1的个数,1的pos的总和还有答案

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=100005;
int n,m;
char s[N];
struct node{
	ll sum,psum,num;
	int l,r;
}t[N*4];
void pushup(int cnt){
	t[cnt].num=t[cnt<<1].num+t[cnt<<1|1].num;
	t[cnt].psum=(t[cnt<<1].psum+t[cnt<<1|1].psum)%mod;
	t[cnt].sum=((t[cnt<<1].sum+t[cnt<<1|1].sum)%mod+(t[cnt<<1].num*t[cnt<<1|1].psum%mod+mod-t[cnt<<1|1].num*t[cnt<<1].psum%mod)%mod)%mod; 
}
void build(int cnt,int l,int r){
	t[cnt].l=l;
	t[cnt].r=r;
	if(l==r){
		if(s[l]=='1'){
		t[cnt].psum=l;
		t[cnt].sum=0;
		t[cnt].num=1;
		}
		else{
			t[cnt].num=t[cnt].psum=t[cnt].num=0;
		}
		return;
	}
	int mid=(l+r)>>1;
	build(cnt<<1,l,mid);
	build(cnt<<1|1,mid+1,r);
	pushup(cnt);
}
void update(int cnt,int pos,int val){
	if(t[cnt].l==t[cnt].r){
		if(val){
		t[cnt].psum=pos;
		t[cnt].sum=0;
		t[cnt].num=1;
		}
		else{
			t[cnt].num=t[cnt].psum=t[cnt].num=0;
		}
		return;
	}
	int mid=(t[cnt].l+t[cnt].r)>>1;
	if(pos<=mid)update(cnt<<1,pos,val);
	else update(cnt<<1|1,pos,val);
	pushup(cnt);
}
int main(){
	scanf("%d",&n);
	scanf("%s",s+1);
	build(1,1,n);
	scanf("%d",&m);
	int q,pos;
	printf("%lld\n",t[1].sum);
	while(m--){
		scanf("%d%d",&q,&pos);
		if(q==1){
			update(1,pos,1);
		}
		else update(1,pos,0);
		printf("%lld\n",t[1].sum);
	}
	return 0;
}

2.牛牛的宝可梦Go

链接

floyed+dp
在图上的dp问题 dp[i]表示在前i个宝可梦且必选i的情况下的最大值,最多200个宝可梦
注意初始化dp数组

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=205;
const int inf=0x3f3f3f3f;
int n,m,dis[N][N],k;
struct node{
	int t,p;
	ll val;
}a[100005];
ll dp[100005];
bool cmp(node x,node y){
	if(x.t==y.t)return x.val>y.val;
	return x.t<y.t;
}
int main(){
	scanf("%d%d",&n,&m);
	memset(dis,inf,sizeof(dis));
	for(int i=1;i<=n;i++){
		dis[i][i]=0;
	}
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		dis[u][v]=dis[v][u]=1;
	}
	for(int p=1;p<=n;p++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				dis[i][j]=min(dis[i][j],dis[i][p]+dis[p][j]);
			}
		}
	}
	
	scanf("%d",&k);
	for(int i=1;i<=k;i++){
		scanf("%d%d%lld",&a[i].t,&a[i].p,&a[i].val);
	}
	a[0]={0,1,0};
	sort(a+1,a+1+k,cmp);
	ll ans=0;
	for(int i=1;i<=k;i++){
		for(int j=1;j<=200;j++){
			if(i-j<0)continue;
			if(a[i].t-a[i-j].t>=dis[a[i].p][a[i-j].p]){
				dp[i]=max(dp[i],dp[i-j]+a[i].val);
			}
		}
		ans=max(ans,dp[i]);
	} 
	printf("%lld\n",ans);
	return 0;
}

四、
1.树上博弈
链接

思路:当两个人之间的距离是偶数的时候先手一定胜,因为一定会把后手逼到叶子节点上,而先手可以顺着后手的路走。奇+奇=偶,偶+偶=偶

这里最好dfs求深度

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=1000005;
const int inf=0x3f3f3f3f;
int n;
int dep[N];
ll cnt[2];
int main(){
	scanf("%d",&n);
	dep[1]=0;
	int f;
	cnt[0]++;
	for(int i=2;i<=n;i++){
		scanf("%d",&f);
		dep[i]=dep[f]^1;
		cnt[dep[i]]++;
	}
	cout<<cnt[0]*(cnt[0]-1)+cnt[1]*(cnt[1]-1)<<endl;
	return 0;
}

2.坐火车
链接

思路:线段树或树状数组。以颜色建树。
以树状数组为例,x可以由x-1推过来,用一个前缀和后缀数组保存x前后不同颜色的个数方便与x和x-1做匹配。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=500005;
const int inf=0x3f3f3f3f;
int n;
struct node{
	int col,l,r;
}a[N];
int pre[N],suf[N];
ll t[N];
int lowbit(int x){
	return x& -x;
}
void add(int x,int v){
	for(int i=x;i<=n;i+=lowbit(i)){
		t[i]+=v;
	}
}
ll query(int x){
	ll ans=0;
	for(int i=x;i;i-=lowbit(i)){
		ans+=t[i];	
	}
	return ans;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d",&a[i].col,&a[i].l,&a[i].r);
		suf[a[i].col]++;
	}
	for(int i=1;i<=n;i++){
		add(a[i].col,-pre[a[i].col]);
		pre[a[i].col]++;
		cout<<query(a[i].r)-query(a[i].l-1)<<" ";
		suf[a[i].col]--;
		add(a[i].col,suf[a[i].col]);
	}
	return 0;
}

3.匹配星星
链接
贪心。对x从小到大排序,将z为0的放入集合,当z为1时查询,这里用二分查询。
multiset可以对集合中的元素排好序并且可以存在重复元素

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=100005;
const int inf=0x3f3f3f3f;
int n;
struct node{
	int x,y,z;
}a[N];
bool cmp(node a,node b){
	if(a.x==b.x&&a.y==b.y)return a.z<b.z;
	if(a.x==b.x)return a.y>b.y;
	return a.x<b.x;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
	}
	int ans=0;
	multiset<int> s;
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		if(a[i].z){
			multiset<int> ::iterator it;
			it=s.lower_bound(a[i].y);
			if(it!=s.begin()){
				it--;
				s.erase(it);
				ans++;
			}
		}
		else s.insert(a[i].y);
	}
	cout<<ans<<endl;
	return 0;
}

五、
1.牛牛战队的比赛地
链接
简单三分。
由题意可得x到各个点的距离和是由大变小再变大的,符合三分条件。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=100005;
const double inf=0x3f3f3f3f;
const double eps=1e-7;
int n;
double ans;
struct node{
	double x,y;
}a[N];
double check(double x){
	double d=0;
	for(int i=1;i<=n;i++){
		double p=sqrt((a[i].x-x)*(a[i].x-x)+a[i].y*a[i].y);
		d=max(d,p);
	}
	return d;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lf%lf",&a[i].x,&a[i].y);
	}
	double l=-10000,r=10000;
	ans=inf;
	while(r-l>eps){
		double lmid=l+(r-l)/3.0;
		double rmid=r-(r-l)/3.0;
		if(check(lmid)<check(rmid))r=rmid;
		else l=lmid;
	}
	printf("%.4lf\n",check(l));
	return 0;
}

2.牛牛与牛妹的约会
链接
两种方式进行比较就好了,注意给出的是速度,所以不足一个单位长度也可以计算

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=100005;
const double inf=0x3f3f3f3f;
const double eps=1e-7;
int n;
int main(){
	int t;
	scanf("%d",&t);
	double a,b;
	while(t--){
		scanf("%lf%lf",&a,&b);
		double ans=0;
		while(1){
			double k1;
			if(a<0){
				k1=-pow(-a,1.0/3.0);
			}
			else k1=pow(a,1.0/3.0);
			if(1+fabs(k1-b)<fabs(a-b)){
				ans+=1.0;
				a=k1;
			}
			else{
				ans+=fabs(a-b);
				break;
			}
			if(a==b)break;
		}
		printf("%.9lf\n",ans);
	}
	return 0;
}

六、
1.图
链接
tarjan
先tarjan出来每个环中的数目,再dfs找如果与环相连就+1.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<cmath>
#include<algorithm>
#include<stack>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int N=1000005;
const double inf=0x3f3f3f3f;
const double eps=1e-7;
int n,e[N],dfn[N],low[N],tot,vis[N],id,ans,bh[N],num[N];
stack<int> s;
void tarjan(int x){
	low[x]=dfn[x]=++tot;
	s.push(x);
	vis[x]=1;
	int v=e[x];
	if(!dfn[v]){
		tarjan(v);
		low[x]=min(low[x],low[v]);
	}
	else if(vis[v]){
		low[x]=min(low[x],dfn[v]); 
	}
	if(low[x]==dfn[x]){
		id++;
		int cnt=0,now;
		vis[x]=0;
		do{
			now=s.top();s.pop();
			vis[now]=0;
			bh[now]=id;
			cnt++;
		}while(now!=x);
		num[id]=cnt;
	}
}
int res[N];
int dfs(int x){
	if(e[x]==x)return 1;
	if(res[x])return res[x];
	if(num[bh[x]]>1)return res[x]=num[bh[x]];
	return res[x]=dfs(e[x])+1;
} 
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&e[i]);
	}
	for(int i=1;i<=n;i++){
		if(!dfn[i]){
			tarjan(i);
		}
	}
	for(int i=1;i<=n;i++){
		ans=max(ans,dfs(i));
	}
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值