菜鸟ACM职业生涯模板总结

基础算法

二分
int bisearch(int l, int r,int x)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}
高精度
//加法
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;

vector<int> add(vector<int> &A, vector<int> &B)
{
    vector<int> C;

    int t = 0; //进位
    for (int i = 0; i < A.size() || i < B.size(); i++)
    {
        if (i < A.size())
            t += A[i];
        if (i < B.size())
            t += B[i];
        C.push_back(t % 10);
        t /= 10;
    }

    if (t)
        C.push_back(1);
    return C;
}
int main()
{
    string a, b;
    int t;
    cin >> t;
    for (int o = 1; o <= t; o++)
    {
        vector<int> A, B;

        cin >> a >> b; //a="123456"
        for (int i = a.size() - 1; i >= 0; i--)
            A.push_back(a[i] - '0'); //A=[6,5,4,3,2,1]
        for (int i = b.size() - 1; i >= 0; i--)
            B.push_back(b[i] - '0');
        auto C = add(A, B); //c++11标准,for循环可以范围遍历;一个变量冒号一个list或容器。
        cout<<"Case "<<o<<":"<<endl;
        cout<<a<<" + "<<b<<" = ";
        for (int i = C.size() - 1; i >= 0; i--)
            printf("%d", C[i]); //个位数先放进去}
        cout<<endl;
        if(o!=t)
        cout<<endl;
    }
}
java大数
import java.util.Scanner;
import java.math.*;

public class Main
{
    public static void main(String[] args) 
    {
        Scanner cin = new Scanner(System.in);
        int t,i=1;
        t=cin.nextInt();
        while(i<=t)
        {
        	i++;
        	BigInteger n,n1,k,bottom;   
        	n=cin.nextBigInteger();
        	BigInteger s1=new BigInteger("1");//1
        	BigInteger s2=new BigInteger("2");//2
        	BigInteger mods=new BigInteger("1000000007");
        	n1=n.add(s1);//n+1
			BigInteger sss;
			
        	BigInteger s12=new BigInteger("12");//12
        	BigInteger nd2;//(n+1)^2
        	nd2=n1.pow(2);
			
        	BigInteger nd21;//(n+1)^2-1
        	nd21=nd2.subtract(s1);//
			
        	k=nd2.multiply(nd21);
        	k=k.divide(s12);
			
        	bottom=n.multiply(n1);
        	BigInteger bottom1,n2n1;
        	bottom1=n.multiply(n1);
        	n2n1=n.multiply(s2);
			n2n1=n2n1.add(s1);
        	bottom1=bottom1.multiply(n2n1);
        	
        	bottom=bottom.multiply(bottom1);
			bottom=bottom.divide(s12);
			//System.out.println(bottom);
			BigInteger ans;
			ans=bottom;
			
        	BigInteger s;
        	s=n.multiply(n1);
        	s=s.divide(s2);
        	s=s.subtract(s1);
        	
        	BigInteger ans2,ks;
			ks=k.multiply(s);
			ans=ans.add(ks);
			System.out.println(ans.mod(mods));
        	ans2=n.pow(2);
        	ans2=ans2.multiply(bottom);
        	System.out.println(ans2.mod(mods));

        }
    }
}

归并排序
void merge_sort(int start,int end){
    if(start>=end){
        return;
    }
    int start1=start,end1=(start+end)/2,start2=end1+1,end2=end;
    merge_sort(start1,end1);
    merge_sort(start2,end2);
    int k=start;
    while(start1<=end1&&start2<=end2){
        arr[k++]=a[start1]<a[start2]?a[start1++]:a[start2++];
    }
    while(start1<=end1){
        arr[k++]=a[start1++];
    }
    while(start2<=end2){
        arr[k++]=a[start2++];
    }
    for(int i=start;i<=end;i++){
        a[i]=arr[i];
    }
}
第k小数
#include <bits/stdc++.h>

using namespace std;
#define ll long long
const int maxn = 5e6 + 10;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}

int q[maxn];
int quick_sort(int q[], int l, int r, int k)
{
    if (l >= r)
        return q[l];
    int i = l - 1, j = r + 1, x = q[l + r >> 1];
    while (i < j)
    {
        do
            i++;
        while (q[i] < x);
        do
            j--;
        while (q[j] > x);
        if (i < j)
            swap(q[i], q[j]);
    }
    if (j - l + 1 >= k)
        return quick_sort(q, l, j, k);
    else
        return quick_sort(q, j + 1, r, k - (j - l + 1));
}
int main()
{
    int n, k;
    int t;
    cin >> t;
    while (t--)

    {
        //scanf("%d%d", &n, &k);
        n=read();
        k=read();
        for (int i = 0; i < n; i++)
            q[i]=read();
        cout << quick_sort(q, 0, n - 1, k) << endl;
    }
}
三分
int three_fen(int l,int r)
{
	while(l<r){
		int m1=(2*l+r)/3;
		int m2=(2*r+l+2)/3;
		if(calc(m1)<=calc(m2))
			r=m2-1;
		else{
			l=m1+1;
		}
	}
	return l;
}
数组模拟双向链表
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=10000015,mod=1e9+7;
template<typename T>
void Debug(T x,string s){
    cout<<s<<": "<<x<<endl;
}
struct node
{
	int val,p_cnt;
	int next,last;
}a[N];

#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
int vis[N],vis_p[N];//value值在链表中的位置,value值对应的数组下标
struct linklist
{
	int head=1,tail=1,sz=0,mid=tail;
	void insertl(int tot){sz++;
		if(sz==1){
			head=tail=tot;vis_p[tot]=0;
			a[tot].last=-1;a[tot].next=-1;
			mid=tail;
		}
		else{
			a[tot].next=head;
			a[tot].last=-1;
			a[head].last=tot;
			vis_p[tot]=vis_p[head]-1;
			head=tot;
			if(sz%2==1){
				movel();
			}
			else{
				mid=mid;
			}
		}
		
	}
	void insertr(int tot){
		sz++;
		if(sz==1){
			head=tail=tot;vis_p[tot]=0;
			a[tot].last=-1;a[tot].next=-1;
			mid=tot;
		}
		else{
			a[tot].last=tail;
			a[tot].next=-1;
			a[tail].next=tot;
			vis_p[tot]=vis_p[tail]+1;
			tail=tot;
			if(sz%2==0){
				mover();
			}
			else mid=mid;
		}
		
	}
	void del(int tot){
		int tl=a[tot].last,tr=a[tot].next;
		if(tr!=-1)
		a[tl].next=tr;
		if(tl!=-1)
		a[tr].last=tl;
		if(tot==head){	
			head=a[head].next;
		}
		if(tot==tail){
			tail=a[tail].last;
		}
			if(vis_p[mid]>vis_p[tot]){
				if(sz%2==1) mover();
				else mid=mid;
			}
			else if(vis_p[mid]<vis_p[tot]){
				if(sz%2==0) movel();
				else mid=mid;
			}
			else if(mid==tot){
				if(sz%2==0) movel();
				else mover();
			}
		sz--;
		a[tot].last=a[tot].next=-1;
	}
	void movel(){
		mid=a[mid].last;
	}
	void mover(){
		mid=a[mid].next;
	}
}List;
int tot=0;
void solve()
{
	int posl=0,posr=0;a[0].last=a[0].next=-1;
	int q;scanf("%d ",&q);char c;
	for(int i=1;i<=q;i++){
		scanf("%c ",&c);
		// cout<<c<<endl;
		if(c=='L'){++tot;
			List.insertl(tot);
		}
		else if(c=='R'){++tot;
			List.insertr(tot);
		}
		else if(c=='G'){
			int x;scanf("%d ",&x);
			List.del(x);
		}
		else{
			printf("%d\n",List.mid);
		}
	}
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("b.txt", "r", stdin);
	freopen("bout.txt", "w", stdout);
#endif
// #ifndef ONLINE_JUDGE
// 	freopen("a.txt", "r", stdin);
// 	freopen("aout.txt", "w", stdout);
// #endif
	int t;
	t=1;
	while (t--)
		solve();
}


快读
template <typename _Tp>
inline _Tp read(_Tp &x) {
    char ch = getchar(), sgn = 0; x = 0;
    while (ch ^ '-' && !isdigit(ch)) ch = getchar();
    if (ch == '-') ch = getchar(), sgn = 1;
    while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
    if (sgn) x = -x;
    return x;
}
int main() {
    b = read(a);
}
//可读int, long long  short

计算程序运行时间
cerr << "Time execute: " << clock() / (double)CLOCKS_PER_SEC << " sec" << endl;
STL离散化
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());

数学

gcd
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
扩展欧几里得
#include<iostream>
#include<cstdio>
#include<cmath>
 
using namespace std;
 
int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法
{
    if(b==0)
    {
        x=1;y=0;
        return a;  //到达递归边界开始向上一层返回
    }
    int r=exgcd(b,a%b,x,y);
    int temp=y;    //把x y变成上一层的
    y=x-(a/b)*y;
    x=temp;
    return r;     //得到a b的最大公因数
}
容斥原理
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int Maxn = 20;
int Number[Maxn + 5];
ll N, M, Tot;
ll Ans = 0;
bool is_prime(int x)
{
	for(int i=2;i*i<=x;i++){
		if(x%i==0) return false;
	}
	return true;
}
ll Gcd(ll A, ll B){
	return !B ? A : Gcd(B, A % B);
}
void Dfs(ll Cur, ll Cnt, ll Limit, ll LCM){
	if (Cnt == Limit) {
		if (Limit & 1) {
			Ans += (N - 1) / LCM;
		}
		else {
			Ans -= (N - 1) / LCM;
		}
		return;
	}
	if (Cur >= Tot) {
		return ;
	}
	ll NowLCM = LCM == -1 ? Number[Cur] : LCM;
	Dfs(Cur + 1, Cnt + 1, Limit, Number[Cur] / Gcd(NowLCM, Number[Cur]) * NowLCM);
	Dfs(Cur + 1, Cnt, Limit, LCM);
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("a.txt","r",stdin);
	freopen("aout.txt","w",stdout);
#endif
	int tot=0;
	// Number[]=2;
	for(int i=2;i<=100;i++){
		if(is_prime(i)){
			Number[++tot]=i;
		}
		if(tot>17) break;
	}
	int t;cin>>t;
	
	while (t--) {
		cin>>N>>M;
		Tot = 1;
		Ans = 0;
		Tot=M+1;
		for (int i = 1; i < Tot; i++) {
			Dfs(1, 0, i, -1);
		} 
		printf("%lld\n", N-Ans-1);
	}
}
卡特兰数
#include<cstdio>
#include<cstring>
#define N 60
using namespace std;
int main()
{
    int h[101][2*N+1],i,j,k,l,n;
    memset(h,0,sizeof(h));
    h[0][1]=1;h[1][1]=1;
    for(i=2;i<=100;i++)
    {
        for(j=0;j<i;j++)
            for(k=1;k<N;k++)
                for(l=1;l<N;l++)
        h[i][k+l-1]+=h[j][k]*h[i-j-1][l];
        for(j=1;j<N;j++)
        {
            h[i][j+1]+=h[i][j]/10;
            h[i][j]%=10;
        }
    }
    while(scanf("%d",&n)!=EOF)
    {
        i=N;
        while(h[n][--i]==0);
        for(j=i;j>0;j--)
        printf("%d",h[n][j]);
        printf("\n");
    }
    return 0;
}
组合数
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=2*150007;
const ll mod=998244353;

 
ll quick_mod(ll a, ll b)
{
    ll ans = 1;
    a %= mod;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % mod;
            b--;
        }
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}
 
ll C(ll n, ll m)
{
    if(m > n) return 0;
    ll ans = 1;
    for(int i=1; i<=m; i++)
    {
        ll a = (n + i - m) % mod;
        ll b = i % mod;
        ans = ans * (a * quick_mod(b, mod-2) % mod) % mod;
    }
    return ans;
}
 
ll Lucas(ll n, ll m)
{
    if(m == 0) return 1;
    return C(n % mod, m % mod) * Lucas(n / mod, m / mod) % mod;
}
//递推公式
const int N = 1e6 + 7, mod = 1e9 + 7;
int n, m, k, t; 
int inv[N];
int fact[N], infact[N];

void init (int n)
{
    fact[0] = infact[0] = inv[0] = inv[1] = 1;
    for (int i = 2; i <= n; ++ i) 
        inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
    for (int i = 1; i <= n; ++ i) {
        fact[i] = 1ll * fact[i - 1] * i % mod;
        infact[i] = 1ll * infact[i - 1] * inv[i] % mod;
    }
}

int C(int n, int m)
{
    if(n < m) return 0;
    if(m == 0 || n == m) return 1;
    return 1ll * fact[n] * infact[m] % mod * infact[n - m] % mod;
}
中国剩余定理
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
 
//扩展欧几里得,ax+by=gcd(a,b) 
ll e_gcd(ll a,ll b,ll &x,ll &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	ll res=e_gcd(b,a%b,y,x);
	y-=(a/b)*x;
	return res;
}
 
//中国剩余定理,pri[]存放互质的数,r[]存放余数,n为个数 
ll china(ll pri[],ll r[],ll n){
	ll M=1,m,d,res=0;
	for(int i=0;i<n;i++) 
		M*=pri[i]; //最小公倍数
	for(int i=0;i<n;i++){
		m=M/pri[i]; //m为除当前这个数不能整除以外都能够被其他数整除,就是其他数的最小公倍数
		ll x,y;
		d=e_gcd(pri[i],m,x,y); // pri[i]*x+m*y=gcd(pri[i],m]
		res=(res+y*m*r[i])%M; 
	} 
	return (res%M+M)%M;  //满足的最小解 
}
 
ll pri[20],r[20];
int main(){
	int n;
	while(~scanf("%d",&n)){
		for(int i=0;i<n;i++)
			scanf("%lld %lld",&pri[i],&r[i]);
		ll ans=china(pri,r,n);
		printf("%lld\n",ans);
	}
} 

素数筛
  • 欧拉筛
#include<bits/stdc++.h>

using namespace std;

const int maxn=1e6;//这个是在哪一个范围内
int prime[maxn];
int visit[maxn];//1代表是偶数,0代表是奇数
void Prime()
{
    memset(visit,0,sizeof(visit));
    memset(prime,0,sizeof(visit));
    visit[1]=1;
    for (int i = 2;i <= maxn; i++) 
    {
        if (!visit[i]) 
        {
            prime[++prime[0]] = i;     
        }
        for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++) 
        {
            visit[i*prime[j]] = 1;
            if (i % prime[j] == 0) 
            {
                break;
            }
        }
    }
}

  • 欧拉筛质因数个数
for(int i=2;i<=10000000;i++)
{
    if(!f[i])prm[++cnt]=i,num[i]=1;
    for(int j=1;j<=cnt && i*prm[j]<=10000000;j++)
    {
        f[i*prm[j]]=true;
        num[i*prm[j]]=num[i]+1;
        if(i%prm[j]==0)break;
    }
}
  • 欧拉函数
void euler()
{
	for (int i = 1; i <N; i++)
		a[i] = i;
	for (int i = 2; i <N; i += 2)
		a[i] /= 2;
	for (int i = 3; i <N; i += 2)
	{
		if (a[i] == i)
			for (int j = i; j <N; j += i)
			{
				if (j % i == 0)
					a[j] = a[j] - a[j] / i;
			}
	}
	a[0]=0;
	for(int i=1;i<N;i++)
	{
		a[i]=a[i-1]+a[i];
	}
}
  • 欧拉降幂
#include<iostream>
using namespace std;
typedef long long ll;
ll read(string s,ll mod){
    ll x=0;
    for(int i=0;i<s.length();i++)
        x=((x<<3)+(x<<1)+(s[i]^48))%mod;
    return (x+mod-1)%mod;
}
ll pow(ll s,ll n,ll mod){
    ll sum=1;
    while(n){
        if(n&1)sum=sum*s%mod;
        s=s*s%mod;
        n>>=1;
    }
    return sum;
}
ll phi(ll x){
    ll t=x;
    for(int i=2;i<=x/i;i++)
        if(x%i==0){
            while(x%i==0)x/=i;
            t=t*(i-1)/i;
        }
    if(x>1)t=t*(x-1)/x;
    return t;
}
int main(){	
    ll x,mod,n;
    string nn;
    cin>>x>>nn>>mod;
    if(x==0){
        if(nn=="1")cout<<1%mod;
        else cout<<"0";
        return 0;
    }
    x%=mod;
    n=read(nn,phi(mod));
    cout<<pow(x%mod,n,mod);
}
逆元
void init(){
	fac[0] = 1;
	for(int i=1;i<=MN;i++)
		fac[i] = (ll)fac[i-1]*i%mod;
	inv[MN] = qpow(fac[MN],mod-2);
	for(int i=MN-1;i>=0;i--)
		inv[i] = (ll)inv[i+1]*(i+1)%mod;
}

int C(int n,int m){
	if(m>n) return 0;
	return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
}


ll pow_mod(ll a, ll b, ll p){//a的b次方求余p
    ll ret = 1;
    while(b){
        if(b & 1) ret = (ret * a) % p;
        a = (a * a) % p;
        b >>= 1;
    }
    return ret;
}
ll Fermat(ll a, ll p){//费马求a关于b的逆元
        return pow_mod(a, p-2, p);
}

质因数分解
bool vis[N];
ll prime[N];
int cnt=0;
void primes()
{
	for(int i=2;i<=N;i++){
		if(vis[i]) {
			continue;
		}
		prime[++cnt]=i;
		for(int j=1;j<=N/i;j++){
			vis[i*j]=1;
		}
	}
}

ll getprimefactor(long long n)
{
	ll ans=0;
	if(n==1){
		return 0;
	}
	if(!vis[N]){
		return 1;
	}
	for(int i=1;i<=cnt&&prime[i]*prime[i]<=n;i++){
		while(n%prime[i]==0){
			ans++;
			n/=prime[i];
		}
	}
	if(n>1){
		return ans+1;
	}
	return ans;
}

数据结构

ST表
void ST_init()
{
    for(int i=1;i<=N;++i)
        ST[i][0]=a[i];
    for(int j=1;j<30;++j)
    {
        for(int i=1;i<=N;++i)
        {
            if(i+(1<<j)-1>N) break;
            ST[i][j]=__gcd(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);
        }
    }
}
 
long long ST_query(int s,int e)
{
    int k=(int)((log(e-s+1.0)/log(2.0)));
    return __gcd(ST[s][k],ST[e-(1<<k)+1][k]);
}


void ST_preowrk()
{
    for(int i=1;i<=n;i++) f[i][0]=a[i];
    int t=log(n)/log(2)+1;
    for(int j=1;j<t;j++){
        for(int i=1;i<=n-(1<<j)+1;i++){
            f[i][j]=max(f[i][j-1],f[i+1<<(j-1)][j-1]);
        }
    }
}

ll ST_query(int l,int r)
{
    int k=log(r-l+1)/log(2);
    return max(f[l][k],f[r-(1<<k)+1][k]);
}
优先队列
#include <iostream>
#include <queue>
using namespace std;
int main()
{
    int n;
    while(cin>>n)
    {
        int i,k,j,t1;
        long long sum=0;
        priority_queue<int,vector<int>,greater<int> > p;
        for(i=0;i<n;i++)
        {
            cin>>k;
            p.push(k);
        }
        while(p.size()!=1)
        {
            t1=p.top();
            p.pop();
            t1+=p.top();
            sum+=t1;
            p.pop();
            p.push(t1);
        }
        cout<<sum<<endl;
    }
}
树状数组
//树状数组模板
int sum[N];
int lowbit(int x)
{
	return x & (-x);
}
void add(int x, int num)
{
	while (x <= n)
	{
		sum[x] += num;
		x += lowbit(x);
	}
}
int ask(int x)
{
	int res = 0;
	while (x > 0)
	{
		res += sum[x];
		x -= lowbit(x);
	}
	return res;
}

单调栈
int tot=0;
h[m+1]=0;
for(int j=1;j<=m+1;j++){
    while(tot&&h[que[tot]]>h[j]){
        ans=max(ans,(j-1-que[tot-1])[que[tot]]);
        //这里可以理解为以 h[que[tot]]个高度可以向左向右拓展的面积。
        tot--;
    }
    que[++tot]=j;
}

线段树
  • 单点修改,区间查询
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100005;
const int INF = 0x3f3f3f3f;
int s[N << 2] ,lc[N << 2] ,rc[N << 2];
int n,m,num[N];
void build(int u ,int l ,int r) {
	lc[u] = l;
	rc[u] = r;
	if(l == r) {
		s[u] = num[l];
		return ;
	}
	int mid = (l + r) / 2;
	build(u * 2 , l , mid);
	build(u * 2 + 1 , mid + 1 ,r);
	s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
void change(int u , int x , int v) {
	if(lc[u] == x && rc[u] == x) {
		s[u] = v;
		return ;
	}
	int mid = (lc[u] + rc[u]) / 2;
	if(x <= mid)
		change(u * 2 , x , v);
	else
		change(u * 2 + 1 , x , v);
	s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
int query(int u , int l ,int r) {
	int res = INF;
	if(l <= lc[u] && r >= rc[u]) {
		return s[u];
	}
	int mid = (lc[u] + rc[u]) / 2;
	if(l <= mid) 
		res = min(res , query(u * 2 , l , r));
	if(r > mid) 
		res = min(res , query(u * 2 + 1 , l , r));
	return res;
}
  • 区间操作lowbit
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&(-x))
const ll mod = 998244353;
ll powmod(ll a,ll b)
{
	ll res=1;a%=mod;
	while(b){
		if(b&1){
			res=res*a%mod;
		}
		a=a*a%mod;
		b>>=1;
	}
	return res;
}

const int N = 1e5+50;
int n,m;
struct node
{
	int l,r;
	ll x,sum;
	int lazy;int flag;
}tree[N<<2];

void push_up(int p)
{
	tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%mod;
	tree[p].flag=(tree[p<<1].flag&tree[p<<1|1].flag);
}

void push_down(int p)
{
	if(tree[p].lazy==0) return;
	tree[p<<1].lazy+=tree[p].lazy;
	tree[p<<1|1].lazy+=tree[p].lazy;
	tree[p<<1].sum=(tree[p<<1].sum*powmod(2,tree[p].lazy))%mod;
	tree[p<<1|1].sum=(tree[p<<1|1].sum*powmod(2,tree[p].lazy))%mod;
	tree[p].lazy=0;
}

void build_tree(int l,int r,int p)
{
	tree[p].l=l,tree[p].r=r;
	tree[p].lazy=tree[p].flag=0;
	if(l==r){
		scanf("%lld",&tree[p].x);
		tree[p].sum=tree[p].x;
		if(lowbit(tree[p].x)==tree[p].x) 
			tree[p].flag=1;
		return;
	}
	int mid=l+r>>1;
	build_tree(l,mid,p<<1);
	build_tree(mid+1,r,p<<1|1);
	push_up(p);
}

void update_tree(int l,int r,int p)
{
	if(l<=tree[p].l&&tree[p].r<=r&&tree[p].flag){
		tree[p].sum=(tree[p].sum*2)%mod;
		tree[p].lazy++;
		return;
	}
	if(tree[p].l==tree[p].r){
		tree[p].x=tree[p].sum=tree[p].sum+lowbit(tree[p].sum);
		if(lowbit(tree[p].x)==tree[p].x){
			tree[p].flag=1;
		}
		return;
	}
	push_down(p);
	int mid=(tree[p].l+tree[p].r)>>1;
	if(l<=mid) update_tree(l,r,p<<1);
	if(mid<r) update_tree(l,r,p<<1|1);
	push_up(p);
}

ll ask_sum(int l,int r,int p)
{
	if(l<=tree[p].l&&tree[p].r<=r){
		return tree[p].sum;
	}
	ll res=0;
	push_down(p);
	int mid=(tree[p].l+tree[p].r)>>1;
	if(l<=mid) {
		res=(res+ask_sum(l,r,p<<1))%mod;
	}
	if(mid<r){
		res=(res+ask_sum(l,r,p<<1|1))%mod;
	}
	return res;
}

void solve()
{
	scanf("%d",&n);
	build_tree(1,n,1);
	scanf("%d",&m);
	int op,l,r;
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&op,&l,&r);
		if(op==1){
			update_tree(l,r,1);
		}
		else{
			printf("%lld\n",ask_sum(l,r,1));
		}
	}
}

int main()
{
	int t;scanf("%d",&t);
	while(t--){
		solve();
	}
}
  • 区间修改,区间查询
#include<bits/stdc++.h>

using namespace std;

const int maxn=100010;

int a[maxn+2];

struct tree{
    int l,r;
    long long pre,add;
}t[4*maxn+2];

void bulid(int p,int l,int r){
    t[p].l=l;t[p].r=r;
    if(l==r){
        t[p].pre=a[l];
        return;
    }
    int mid=l+r>>1;
    bulid(p*2,l,mid);
    bulid(p*2+1,mid+1,r);
    t[p].pre=t[p*2].pre+t[p*2+1].pre;
} 

void spread(int p){
    if(t[p].add){
        t[p*2].pre+=t[p].add*(t[p*2].r-t[p*2].l+1);
        t[p*2+1].pre+=t[p].add*(t[p*2+1].r-t[p*2+1].l+1);
        t[p*2].add+=t[p].add;
        t[p*2+1].add+=t[p].add;
        t[p].add=0;
    }
}

void change(int p,int x,int y,int z){
    if(x<=t[p].l && y>=t[p].r){
        t[p].pre+=(long long)z*(t[p].r-t[p].l+1);
        t[p].add+=z;
        return;
    }
    spread(p);
    int mid=t[p].l+t[p].r>>1;
    if(x<=mid) change(p*2,x,y,z);
    if(y>mid) change(p*2+1,x,y,z);
    t[p].pre=t[p*2].pre+t[p*2+1].pre;   
}

long long ask(int p,int x,int y){
    if(x<=t[p].l && y>=t[p].r) return t[p].pre;
    spread(p);
    int mid=t[p].l+t[p].r>>1;
    long long ans=0;
    if(x<=mid) ans+=ask(p*2,x,y);
    if(y>mid) ans+=ask(p*2+1,x,y);
    return ans;
}

int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    bulid(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int q,x,y,z;
        scanf("%d",&q);
        if(q==1){
            scanf("%d%d%d",&x,&y,&z);
            change(1,x,y,z);
        }
        else {
            scanf("%d%d",&x,&y);
            cout<<ask(1,x,y)<<endl;
        }
    }
    return 0;
}
//问最小值
//Q a b 询问(a,b)中最小值
//C a b 将a点值改为b
#include <bits/stdc++.h>
using namespace std;
#define maxn 200005
 
int min(int a, int b)
{
	return a>b ? b : a;
}
int tree[4 * maxn];
 
void pushup(int i)
{
	tree[i] = min(tree[i << 1], tree[i << 1 | 1]);
}
 
void build(int i, int l, int r)
{
	if (l == r)
	{
		scanf("%lld", &tree[i]);
		return;
	}
	int mid = (l + r) / 2;
	build(i << 1, l, mid);
	build(i << 1 | 1, mid + 1, r);
	pushup(i);
}
 
void update(int i, int l, int r, int x, int val)
{
	if (l == r)///l==x??±???
	{
		tree[i] = val;
		return;
	}
	int mid = (l + r) / 2;
	if (x <= mid) update(i << 1, l, mid, x, val);
	else update(i << 1 | 1, mid + 1, r, x, val);
	pushup(i);
}
 
int query(int i, int l, int r, int x, int y)
{
	if (x <= l && r <= y)
		return tree[i];
	int minn = 9999999;
	int mid = (l + r) / 2;
	if (x <= mid) minn = min(minn, query(i << 1, l, mid, x, y));
	if (y>mid) minn = min(minn, query(i << 1 | 1, mid + 1, r, x, y));
	return minn;
}
 
int main()
{
	int n, m;
	int b, c;
	char a;
	while (scanf("%d%d", &n, &m) != -1)
	{
		build(1, 1, n);
		while (m--)
		{
			scanf(" %c%d%d", &a, &b, &c);
			if (a == 'Q')
				printf("%d\n", query(1, 1, n, b, c));
			else
				update(1, 1, n, b, c);
		}
	}
	return 0;
}



#include <bits/stdc++.h>
using namespace std;
#define maxn 200005
int tree[4 * maxn];
 
void pushup(int i)
{
	tree[i] = max(tree[i << 1], tree[i << 1 | 1]);
}
 
void build(int i, int l, int r)
{
	if (l == r)
	{
		tree[i] = 0;
		return;
	}
	int mid = (l + r) / 2;
	build(i << 1, l, mid);
	build(i << 1 | 1, mid + 1, r);
	pushup(i);
}
 
void update(int i, int l, int r, int x, int val)
{
	if (l == r)
	{
		tree[i] = val;
		return;
	}
	int mid = (l + r) / 2;
	if (x <= mid) update(i << 1, l, mid, x, val);
	else update(i << 1 | 1, mid + 1, r, x, val);
	pushup(i);
}
 
int query(int i, int l, int r, int x, int y)
{
	if (x <= l && r <= y)
		return tree[i];
	int maxm = 0;
	int mid = (l + r) / 2;
	if (x <= mid) maxm = max(maxm, query(i << 1, l, mid, x, y));
	if (y>mid) maxm = max(maxm, query(i << 1 | 1, mid + 1, r, x, y));
	return maxm;
}
 
int main()
{
	int n, m;
	int b, c;
	char a;
	while (~scanf("%d%d", &n, &m))
	{
		build(1, 1, n);
		while (m--)
		{
			scanf(" %c%d%d", &a, &b, &c);
			if (a == 'Q')
				printf("%d\n", query(1, 1, n, b, c));
			else
				update(1, 1, n, b, c);
		}
	}
}
主席树
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e5;  // 数据范围
int tot, n, m;
int sum[(maxn << 5) + 10], rt[maxn + 10], ls[(maxn << 5) + 10],
    rs[(maxn << 5) + 10];
int a[maxn + 10], ind[maxn + 10], len;
inline int getid(const int &val) {  // 离散化
  return lower_bound(ind + 1, ind + len + 1, val) - ind;
}
int build(int l, int r) {  // 建树
  int root = ++tot;
  if (l == r) return root;
  int mid = l + r >> 1;
  ls[root] = build(l, mid);
  rs[root] = build(mid + 1, r);
  return root;  // 返回该子树的根节点
}
int update(int k, int l, int r, int root) {  // 插入操作
  int dir = ++tot;
  ls[dir] = ls[root], rs[dir] = rs[root], sum[dir] = sum[root] + 1;
  if (l == r) return dir;
  int mid = l + r >> 1;
  if (k <= mid)
    ls[dir] = update(k, l, mid, ls[dir]);
  else
    rs[dir] = update(k, mid + 1, r, rs[dir]);
  return dir;
}
int query(int u, int v, int l, int r, int k) {  // 查询操作
  int mid = l + r >> 1,
      x = sum[ls[v]] - sum[ls[u]];  // 通过区间减法得到左儿子的信息
  if (l == r) return l;
  if (k <= x)  // 说明在左儿子中
    return query(ls[u], ls[v], l, mid, k);
  else  // 说明在右儿子中
    return query(rs[u], rs[v], mid + 1, r, k - x);
}
inline void init() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; ++i) scanf("%d", a + i);
  memcpy(ind, a, sizeof ind);
  sort(ind + 1, ind + n + 1);
  len = unique(ind + 1, ind + n + 1) - ind - 1;
  rt[0] = build(1, len);
  for (int i = 1; i <= n; ++i) rt[i] = update(getid(a[i]), 1, len, rt[i - 1]);
}
int l, r, k;
inline void work() {
  while (m--) {
    scanf("%d%d%d", &l, &r, &k);
    printf("%d\n", ind[query(rt[l - 1], rt[r], 1, len, k)]);  // 回答询问
  }
}
int main() {
  init();
  work();
  return 0;
}
  • 查询前k大和
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 7;
int root[MAXN],n,q,size,num;//size 内存池的大小
ll a[MAXN],s[MAXN],b[MAXN];

struct HJT_tree{
	int l,r,cnt;//cnt记录出现次数 sum记录和 val记录节点的值
	ll sum,val;
}tree[MAXN*40];

void build(int &now,int l,int r){
	now = ++size;
	tree[now].cnt = tree[now].sum = tree[now].val = 0;
	if(l == r) return ;
	int mid = (l+r)>>1;
	build(tree[now].l,l,mid);
	build(tree[now].r,mid+1,r);
}

void modify(int &now,int pre,int l,int r,int p,int val){
	tree[now = ++size] = tree[pre];
	tree[now].cnt++,tree[now].sum += val;
	if(l == r){
		tree[now].val = val;
		return ;
	}
	int mid = (l+r)>>1;
	if(p <= mid) modify(tree[now].l,tree[pre].l,l,mid,p,val);
	else modify(tree[now].r,tree[pre].r,mid+1,r,p,val);
}
//查前k大值,因为节点存的是值 所以找大的 应该先往右边找 看右边(也就是大的)的数量符合情况嘛
ll query(int now,int pre,int l,int r,int k){
	if(l == r) return tree[now].val * k;//因为一个值可能出现多次 那么计算答案的时候要把他们都算上
	int mid = (l+r)>>1;
	int tmp = tree[tree[now].r].cnt - tree[tree[pre].r].cnt;
	if(tmp >= k) return query(tree[now].r,tree[pre].r,mid+1,r,k);
	else return query(tree[now].l,tree[pre].l,l,mid,k-tmp) + 
				tree[tree[now].r].sum - tree[tree[pre].r].sum;//注意左边的k要变成k-tmp的形式
}

int getid(ll x){ return lower_bound(b+1,b+1+num,x)-b; }

int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		memset(root,0,sizeof(root));
		size = 0;
		scanf("%d",&n);
		for(int i = 1;i <= n;i ++){
			scanf("%lld",&a[i]);
			b[i] = a[i];
			s[i] = s[i-1] + (1ll*i*i);//这里i会爆 所以开ll
		}
		/*****离散化 + 初始化****/
		sort(b+1,b+1+n);
		num = unique(b+1,b+1+n)-b-1;
		build(root[0],1,num);
		/***********************/
		for(int i = 1;i <= n;i ++){
			int p = getid(a[i]);
			modify(root[i],root[i-1],1,num,p,a[i]);
		}
		scanf("%d",&q);
		int l,r,k;
		while(q--){
			scanf("%d%d%d",&l,&r,&k);
			ll ans = query(root[r],root[l-1],1,num,k);
			ans += s[r-l+1];
			printf("%lld\n",ans);
		}
	}
	return 0;
}

树上倍增求LCA
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1000010;
inline void read(int &n)
{
    char c=getchar();bool flag=0;n=0;
    while(c<'0'||c>'9')	c=='-'?flag=1,c=getchar():c=getchar();
    while(c>='0'&&c<='9')	n=n*10+c-48,c=getchar();flag==1?n=-n:n=n;
}
struct node
{
    int v,nxt;
}edge[MAXN];
int head[MAXN];
int num=1;
inline void add_edge(int x,int y)
{
    edge[num].v=y;
    edge[num].nxt=head[x];
    head[x]=num++;
}
int f[MAXN][21];
int deep[MAXN];
int n,m,root;
void dfs(int now)
{
    for(int i=head[now];i!=-1;i=edge[i].nxt)
        if(!deep[edge[i].v])
            deep[edge[i].v]=deep[now]+1,f[edge[i].v][0]=now,dfs(edge[i].v);
}
void PRE()
{
    for(int i=1;i<=19;i++)	
        for(int j=1;j<=n;j++)
            f[j][i]=f[f[j][i-1]][i-1];
} 
int LCA(int x,int y)
{
    if(deep[x]<deep[y])	swap(x,y);//x是靠下的那个。
    for(int i=19;i>=0;i--)
        if(deep[f[x][i]]>=deep[y])
            x=f[x][i];
    if(x==y)	return x;
    for(int i=19;i>=0;i--)
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    return	f[x][0];
}
int main()
{
    
    memset(head,-1,sizeof(head));
    read(n);read(m);read(root);
    for(int i=1;i<=n-1;i++)
    {
        int x,y;read(x);read(y);
        add_edge(x,y);
        add_edge(y,x);
    }
    deep[root]=1;
    dfs(root);
    PRE();
    for(int i=1;i<=m;i++)
    {
        int x,y;
        read(x);read(y);
        printf("%d\n",LCA(x,y));
    }
    return 0;
} 
树链剖分
void dfs1(int o) {
  son[o] = -1;
  siz[o] = 1;
  for (int j = h[o]; j; j = nxt[j])
    if (!dep[p[j]]) {
      dep[p[j]] = dep[o] + 1;
      fa[p[j]] = o;
      dfs1(p[j]);
      siz[o] += siz[p[j]];
      if (son[o] == -1 || siz[p[j]] > siz[son[o]]) son[o] = p[j];
    }
}
void dfs2(int o, int t) {
  top[o] = t;
  cnt++;
  dfn[o] = cnt;
  rnk[cnt] = o;
  if (son[o] == -1) return;
  dfs2(son[o], t);  // 优先对重儿子进行 DFS,可以保证同一条重链上的点 DFS 序连续
  for (int j = h[o]; j; j = nxt[j])
    if (p[j] != son[o] && p[j] != fa[o]) dfs2(p[j], p[j]);
}
莫队
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 100010;

int n,m,blo;
int l=1,r=0;
int c[maxn],cnt[maxn],pos[maxn];
ll res=0;

struct Q{
    int l,r,id;
}q[maxn];
struct Ans{
    ll a,b;
}ans[maxn];

bool cmp(Q a,Q b){
    if(pos[a.l]==pos[b.l]) return a.r<b.r;
    return a.l<b.l;
}

void add(int i){
    res-=1ll*cnt[c[i]]*cnt[c[i]];
    ++cnt[c[i]];
    res+=1ll*cnt[c[i]]*cnt[c[i]];
}

void del(int i){
    res-=1ll*cnt[c[i]]*cnt[c[i]];
    --cnt[c[i]];
    res+=1ll*cnt[c[i]]*cnt[c[i]];
}

ll gcd(ll a,ll b){
    if(a<b) swap(a,b); 
    return b==0?a:gcd(b,a%b);
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
    n=read(),m=read();
    blo=sqrt(n);
    for(int i=1;i<=n;i++) c[i]=read(),pos[i]=(i-1)/blo+1;
    for(int i=1;i<=m;i++){
        q[i].l=read(),q[i].r=read();
        q[i].id=i;
    }
    
    sort(q+1,q+1+m,cmp); 
    
    for(int i=1;i<=m;i++){
        while(l<q[i].l){ del(l); l++; }
        while(l>q[i].l){ add(l-1); l--; }
        while(r<q[i].r){ add(r+1); r++; }
        while(r>q[i].r){ del(r); r--; }
        
        if(q[i].l==q[i].r){
            ans[q[i].id]=(Ans){0,1};
            continue;
        }
        ans[q[i].id]=(Ans){res-(r-l+1),1ll*(r-l+1)*(r-l)};
    }
    
    for(int i=1;i<=m;i++){
        ll g=gcd(ans[i].a,ans[i].b);
        printf("%lld/%lld\n",ans[i].a/g,ans[i].b/g); 
    }
    
    return 0;
}

字符串

字典树
#include <bits/stdc++.h>

using namespace std;

#define PII pair<int,int> 
typedef long long ll;
const int maxn = 1e3 + 7;
const int N = 4e6 + 7;
char mp[maxn][maxn];
char str[maxn],t[maxn];
int n,m;
int trie[N][26],idx,val[N];

void insert(char *s,int x)
{
    int p = 0,len = strlen(s);
    for(int i = 0;i < len;i ++){
        int ch = s[i] - 'a';
        if(!trie[p][ch]) trie[p][ch] = ++idx;
        p = trie[p][ch];
    }
    val[p] = x;
}

int query(char *s)
{
    int p = 0,len = strlen(s);
    for(int i = 0;i < len;i ++){
        int ch = s[i] - 'a';
        p = trie[p][ch];
        if(!p) return -1;
    }
    if(val[p]) return val[p];
    else return -1;
}

void init()
{
    for(int i = 0;i <= idx;i ++){
        memset(trie[i],0,sizeof(trie[i]));
        val[i] = 0;
    }
    idx = 0;
}

int main()
{
    int tt;scanf("%d",&tt);
    while(tt--){
        init();
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;i++){
            scanf("%s",mp[i]+1);
        }
        while(m--){
            int x;scanf("%s%d",str,&x);
            insert(str,x);
        }
        int flag = 0;ll sum = 0;
        for(int i = 1;i <= n;i++){
            for(int j = 1;j <= n;j++ ){
                int len = 0;
                if(mp[i][j] == '#') continue;
                while(mp[i][j] != '#' && j <= n){
                    t[len++] = mp[i][j];
                    j++;
                }
                t[len] = '\0';
                int ans = query(t);
                if(ans == -1) flag = 1;
                else sum += ans;
            }
        }
        for(int j=1;j<=n;j++){
            for(int i=1;i<=n;i++){
                int len = 0;
                if(mp[i][j] == '#') continue;
                while(mp[i][j] !='#'&& i <= n){
                    t[len++] = mp[i][j];
                    i++;
                }
                t[len] = '\0';
                int ans = query(t);
                if(ans == -1) flag = 1;
                else sum += ans;
            }
        }    
        if(flag) printf("-1\n");
        else printf("%lld\n",sum);               
    }   
}
字符串hash
#include<iostream>
#include<algorithm>

using namespace std;

typedef unsigned long long ULL;
const int N=1e6+10,M=131;

int n,m;
char str[N];

ULL p[N],h[N];
ULL get(int l,int r)
{
	return h[r]-h[l-1]*p[r-l+1];
}

int main()
{
	cin>>n>>m;
	cin>>str+1;
	p[0]=1;
	for(int i=1;i<=n;i++)
	{
		h[i]=h[i-1]*M+str[i];
		p[i]=p[i-1]*M;
	}
	while(m--)
	{
		int l1,r1,l2,r2;
		cin>>l1>>r1>>l2>>r2;
		if(get(l1,r1)==get(l2,r2)) puts("Yes");
		else
		puts("No");
	}
	return 0;
}

图论

图的连通子图
#include<bits/stdc++.h> 
const int N=1005;
using namespace std;
vector<int> t[N]; 
int vis[N]={0};
void dfs(int k)
{
    for(int i=0;i<t[k].size();i++)
    {
        if(vis[t[k][i]]==0)
        {   vis[t[k][i]]=1;
            dfs(t[k][i]);
        }
    }
}
int main()
{
    int n,m;//n个顶点,m条边 
    cin>>n>>m;
    int a,b;//边所连接的两个顶点
    for(int i=1;i<=m;i++)
    {
        cin>>a>>b;
        t[a].push_back(b);
        t[b].push_back(a);
    }
    
    int ans=0;//记录连通块数量 
    for(int i=1;i<=n;i++)
    {
        if(vis[i]==0)
        {
            vis[i]=1;
            dfs(i);
            ans++; 
        }      
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int maxn = 3e5 + 3;
int edge[maxn][maxn];
vector<int> t[maxn];
int pre[maxn], root[maxn];

void init(int nn)
{
    for (int i = 1; i <= nn; i++)
        pre[i] = i;
}
int find(int x)
{
    int f = x;
    while (x != pre[x]) //找到x的父节点
        x = pre[x];
    int j;
    while (f != pre[f]) //依次将x上面的节点的父节点赋为x;
    {
        j = f;
        f = pre[f];
        pre[j] = x;
    }
    return x;
}

void merge(int a, int b)
{
    int t1, t2;
    t1 = find(a);
    t2 = find(b);
    if (t1 != t2)
    {
        pre[t2] = t1;
    }
}

int block(int nn)
{
    int ans = 0;
    for (int i = 1; i <= nn; i++)
        root[pre[i]] = 1;
    for (int i = 1; i <= nn; i++)
        ans += root[i];
    return ans;
}

int main()
{
    int n, m;
    cin >> n >> m;
    init(n);
    for (int i = 1; i <= m; i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        t[a].push_back(b);
        t[b].push_back(a);
        // merge(a, b);
    }
    for (int i = 1; i <= n; i++)
    {
        vector<int>::iterator it;
        for(it=t[i].begin();it!=t[i].size())
        printf("%d",block(n));
    }
}

// void init(int nn)
// {
//     for(int i=1;i<=nn;i++)
//     pre[i]=i;
// }
// int find(int x)
// {
//     int f=x;
//     while(x!=pre[x])//找到x的父节点
//     x=pre[x];

//     int j;
//     while(f!=pre[f])//依次将x上面的节点的父节点赋为x;
//     {
//         j=f;
//         f= pre[f];
//         pre[j]=x;
//     }
//     return x;
// }

// void merge(int a,int b)
//  {
//      int t1,t2;
//      t1=find(a);
//      t2=find(b);
//      if(t1!=t2)
//      {
//          pre[t2]=t1;
//      }
// }

// int block(int nn)
// {
//     int ans=0;
//     for(int i=1;i<=nn;i++)
//     root[pre[i]]=1;
//     for(int i=1;i<=nn;i++)
//     ans+=root[i];
//     return ans;
// }
// int main()
// {
//     scanf("%d%d",&n,&m);
//     int a,b;//边所连接的两个顶点
//     init(n);
//     for(int i=1;i<=m;i++)
//     {
//         scanf("%d%d",&a,&b);
//         t[a].push_back(b);
//         t[b].push_back(a);
//         merge(a,b);
//     }
//     printf("%d",block(n));
//     return 0;
// }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂的码泰君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值