• @一句话题解


    省选貌似已经定在了 5 月 31 日,WC 貌似已经流水。感觉少经历了一次WC有点可惜。

    不过现在来看 THUWC2020 是真的逃过一劫。还好没有真的在 2020 年举办。

    加油吧。

    codeforces - 528C:(本题的难点在于理解题意)要求定向后每个点出度和入度都为偶数,只需要满足(1)定向前每个点度数为偶数(2)整张图有偶数条边。前一个条件直接把奇点两两相连,后一个条件随便找个点连个自环。然后求出 dfs 树从下往上调整。注意处理自环重边。

    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 100000;
    const int MAXM = 300000;
    
    struct edge{
    	int to; edge *nxt, *rev;
    }edges[2*MAXM + 5], *adj[MAXN + 5], *ecnt = edges;
    void addedge(int u, int v) {
    	if( u != v ) {
    		edge *p = (++ecnt), *q = (++ecnt);
    		p->to = v, p->nxt = adj[u], adj[u] = p;
    		q->to = u, q->nxt = adj[v], adj[v] = q;
    		p->rev = q, q->rev = p;
    	}
    	else {
    		edge *p = (++ecnt);
    		p->to = v, p->nxt = adj[u], adj[u] = p;
    	}
    }
    
    int dfn[MAXM + 5], dcnt;
    vector<pair<int, int> >ans;
    int dfs(int x, edge *f) {
    	int cnt = 0; dfn[x] = (++dcnt);
    	for(edge *p=adj[x];p;p=p->nxt) {
    		if( p == f ) continue;
    		if( !dfn[p->to] ) {
    			if( dfs(p->to, p->rev))
    				ans.push_back(make_pair(x, p->to));
    			else ans.push_back(make_pair(p->to, x)), cnt ^= 1;
    		}
    		else if( dfn[p->to] <= dfn[x] )
    			ans.push_back(make_pair(p->to, x)), cnt ^= 1;
    	}
    	return cnt;
    }
    
    int deg[MAXN + 5];
    int main() {
    	int n, m; scanf("%d%d", &n, &m);
    	for(int i=1;i<=m;i++) {
    		int a, b; scanf("%d%d", &a, &b);
    		deg[a]++, deg[b]++, addedge(a, b);
    	}
    	int lst = 0;
    	for(int i=1;i<=n;i++) {
    		if( deg[i] & 1 ) {
    			if( lst == 0 ) lst = i;
    			else addedge(lst, i), lst = 0;
    		}
    	}
    	if( dfs(1, NULL) ) ans.push_back(make_pair(1, 1));
    	
    	printf("%d
    ", ans.size());
    	for(int i=0;i<ans.size();i++)
    		printf("%d %d
    ", ans[i].first, ans[i].second);
    }
    

    atcoder - AGC029E:记 mx[x] 表示 x 到 1(除了 x)的最大点,再记 f(x, k) 表示从 x 出发经过 <= k(除了 x)的点的点数。则 ans[x] = ans[mx[x]] + f(x, mx[x] - 1),即我们一旦走过 mx[x] 就不会回头。但是这样算 f(mx[x], mx[mx[x]] - 1) 可能会算重。因此如果算重了,需要再减去 f(x 到 mx[x] 的路径上距离 mx[x] 最近的点, mx[mx[x]] - 1)。f 并查集离线算。

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 200000;
    
    vector<int>G[MAXN + 5], q1[MAXN + 5], q2[MAXN + 5];
    void addedge(int u, int v) {
    	G[u].push_back(v), G[v].push_back(u);
    }
    
    int mx[MAXN + 5], pos[MAXN + 5];
    void dfs1(int x, int f, int m, int p) {
    	mx[x] = m, pos[x] = p;
    	if( x > m ) {
    		for(int i=0;i<G[x].size();i++)
    			if( G[x][i] != f ) dfs1(G[x][i], x, x, G[x][i]);
    	}
    	else {
    		for(int i=0;i<G[x].size();i++)
    			if( G[x][i] != f ) dfs1(G[x][i], x, m, p);
    	}
    	if( x != 1 ) {
    		q1[mx[x] - 1].push_back(x);
    		if( pos[x] == x && mx[mx[x]] > x )
    			q2[mx[mx[x]] - 1].push_back(x);
    	}
    }
    int ans[MAXN + 5], g[MAXN + 5];
    void dfs2(int x, int f) {
    	if( x != 1 ) {
    		if( pos[x] == x ) g[x] += ans[mx[x]];
    		ans[x] += g[pos[x]];
    	}
    	for(int i=0;i<G[x].size();i++)
    		if( G[x][i] != f ) dfs2(G[x][i], x);
    }
    
    bool tag[MAXN + 5]; int fa[MAXN + 5], siz[MAXN + 5];
    int find(int x) {return fa[x] = (fa[x] == x ? x : find(fa[x]));}
    void unite(int x, int y) {
    	int fx = find(x), fy = find(y);
    	fa[fx] = fy, siz[fy] += siz[fx];
    }
    void add(int &sum, int x) {
    	x = find(x);
    	if( !tag[x] ) {
    		tag[x] = true;
    		sum += siz[find(x)];
    	}
    }
    void erase(int x) {tag[find(x)] = false;}
    
    int main() {
    	int N; scanf("%d", &N);
    	for(int i=1;i<N;i++) {
    		int u, v; scanf("%d%d", &u, &v);
    		addedge(u, v);
    	}
    	dfs1(1, 0, 0, 1);
    	for(int i=1;i<=N;i++) fa[i] = i, siz[i] = 1;
    	for(int i=0;i<=N;i++) {
    		for(int j=0;j<G[i].size();j++)
    			if( G[i][j] <= i ) unite(i, G[i][j]);
    		for(int j=0;j<q1[i].size();j++) {
    			int x = q1[i][j], s = 0;
    			for(int p=0;p<G[x].size();p++)
    				if( G[x][p] <= i ) add(s, G[x][p]);
    			add(s, x), ans[x] += s;
    			
    			for(int p=0;p<G[x].size();p++)
    				if( G[x][p] <= i ) erase(G[x][p]);
    			erase(x);
    		}
    		for(int j=0;j<q2[i].size();j++) {
    			int x = q2[i][j], s = 0;
    			for(int p=0;p<G[x].size();p++)
    				if( G[x][p] <= i ) add(s, G[x][p]);
    			add(s, x), g[x] -= s;
    			
    			for(int p=0;p<G[x].size();p++)
    				if( G[x][p] <= i ) erase(G[x][p]);
    			erase(x);
    		}
    		
    	}
    	ans[1] = 1; dfs2(1, 0);
    	for(int i=2;i<=N;i++)
    		printf("%d%c", ans[i] - 1, (i == N ? '
    ' : ' '));
    }
    

    codeforces - 1039D:最大长度为 i 的链剖分等价于最大长度 >= i 的链剖分。可以类比 noip2018d1t3 的贪心,能够子树内部匹配的就不往子树外部匹配,O(n) 贪心一波。注意到答案单调递减,且对于 i 答案上界为 n/i,因此当 > (O(sqrt{nlog n})) 时二分找相同答案右端点可以做到 (O(nsqrt{nlog n}))。略卡常,将递归换成扫 dfs 序。

    #include <cstdio>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 100000;
    const int SQRT = 1100;
    
    vector<int>G[MAXN + 5];
    void addedge(int u, int v) {
    	G[u].push_back(v), G[v].push_back(u);
    }
    
    int dfn[MAXN + 5], fa[MAXN + 5], dcnt;
    void dfs(int x, int f) {
    	dfn[++dcnt] = x, fa[x] = f;
    	for(int i=0;i<G[x].size();i++)
    		if( G[x][i] != f ) dfs(G[x][i], x);
    }
    
    int mx[MAXN + 5], smx[MAXN + 5], f[MAXN + 5], g[MAXN + 5], n;
    
    int solve(int x) {
    	for(register int i=1;i<=n;i++) mx[i] = smx[i] = f[i] = 0;
    	for(register int i=n;i>=1;i--) {
    		int k = dfn[i];
    		if( mx[k] + smx[k] + 1 >= x )
    			f[k]++, g[k] = 0;
    		else g[k] = mx[k] + 1;
    		
    		if( fa[k] ) {
    			f[fa[k]] += f[k];
    			if( g[k] > mx[fa[k]] )
    				smx[fa[k]] = mx[fa[k]], mx[fa[k]] = g[k];
    			else if( g[k] > smx[fa[k]] )
    				smx[fa[k]] = g[k];
    		}
    	}
    	return f[1];
    }
    
    int ans[MAXN + 5];
    int main() {
    	scanf("%d", &n);
    	for(int i=1;i<n;i++) {
    		int u, v; scanf("%d%d", &u, &v);
    		addedge(u, v);
    	}
    	dfs(1, 0); int p;
    	for(p = 1; p <= SQRT && p <= n; p++)
    		ans[p] = solve(p);
    	for(; p <= n;) {
    		int x = solve(p), l = p, r = n;
    		while( l < r ) {
    			int m = (l + r + 1) >> 1;
    			if( solve(m) >= x )
    				l = m;
    			else r = m - 1;
    		}
    		for(; p <= l; p++) ans[p] = x;
    	}
    	
    	for(int i=1;i<=n;i++) printf("%d
    ", ans[i]);
    }
    

    hdu - 5306:segment tree beats 模板题。我也不知道为啥跑得很慢。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    
    const int MAXN = 1000000;
    
    int read() {
        int x = 0; char ch = getchar();
        while( ch > '9' || ch < '0' ) ch = getchar();
        while( '0' <= ch && ch <= '9' ) x = 10*x + ch - '0', ch = getchar();
        return x;
    }
    
    void write(ll x, bool _=false) {
        if( !x ) {
            if( !_ ) putchar('0');
            return ;
        }
        write(x / 10, true), putchar(x % 10 + '0');
    }
    
    struct type{
        int mx, smx, mc; type() {}
        type(int _mx, int _smx, int _mc) : mx(_mx), smx(_smx), mc(_mc) {}
        friend type merge(const type &a, const type &b) {
            if( a.mx == b.mx ) return type(a.mx, max(a.smx, b.smx), a.mc + b.mc);
            else if( a.mx > b.mx ) return type(a.mx, max(a.smx, b.mx), a.mc);
            else return type(b.mx, max(a.mx, b.smx), b.mc);
        }
    };
    
    int a[MAXN + 5], n, m;
    
    namespace segtree{
        #define lch (x << 1)
        #define rch (x << 1 | 1)
        
        int le[4*MAXN + 5], ri[4*MAXN + 5];
        type t[4*MAXN + 5]; ll s[4*MAXN + 5];
        
        void maintain(int x, int k) {
            if( k < t[x].mx )
                s[x] -= 1LL*(t[x].mx - k)*t[x].mc, t[x].mx = k;
        }
        void pushdown(int x) {maintain(lch, t[x].mx), maintain(rch, t[x].mx);}
        void pushup(int x) {s[x] = s[lch] + s[rch], t[x] = merge(t[lch], t[rch]);}
        void build(int x, int l, int r) {
            le[x] = l, ri[x] = r;
            if( l == r ) {
                t[x] = type(a[l], -1, 1); s[x] = a[l];
                return ;
            }
            int m = (l + r) >> 1;
            build(lch, l, m), build(rch, m + 1, r);
            pushup(x);
        }
        void modify(int x, int l, int r, int k) {
            if( l <= le[x] && ri[x] <= r && t[x].smx < k ) {
                maintain(x, k);
                return ;
            }
            if( l > ri[x] || r < le[x] || k >= t[x].mx ) return ;
            pushdown(x);
            modify(lch, l, r, k), modify(rch, l, r, k);
            pushup(x);
        }
        int query(int x, int l, int r) {
            if( l <= le[x] && ri[x] <= r ) return t[x].mx;
            if( l > ri[x] || r < le[x] ) return -1;
            pushdown(x); return max(query(lch, l, r), query(rch, l, r));        
        }
        ll sum(int x, int l, int r) {
            if( l <= le[x] && ri[x] <= r ) return s[x];
            if( l > ri[x] || r < le[x] ) return 0;
            pushdown(x); return sum(lch, l, r) + sum(rch, l, r);
        }
    }
    
    
    void solve() {
        n = read(), m = read();
        for(int i=1;i<=n;i++) a[i] = read();
        segtree::build(1, 1, n);
        for(int i=1;i<=m;i++) {
            int op = read(), x = read(), y = read(), t;
            if( op == 0 ) t = read(), segtree::modify(1, x, y, t);
            else if( op == 1 ) write(segtree::query(1, x, y)), puts("");
            else write(segtree::sum(1, x, y)), puts("");
        }
    }
    
    int main() {int _ = read(); while( _-- ) solve();}
    

    bzoj - 4695:稍微复杂一点的 Segment Tree Beats。可以把区间取 max/min 看作区间内 min/max 值整体加减。因为打 tag 会导致 min/max 值变化(反正我写的代码会变化)所以需要先处理出儿子的 min/max 是否与父亲相同。偷了个 fread 刚好卡过。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    
    const int INF = int(1E9);
    const int MAXN = 500000;
    
    #define gc if(++ip==ie)fread(ip=buf,1,SZ,stdin)
    const int SZ=1<<19;
    char buf[SZ],*ie=buf+SZ,*ip=ie-1;
    inline int read(){
        gc;while(*ip<'-')gc;
        bool f=*ip=='-';if(f)gc;
        int x=*ip&15;gc;
        while(*ip>'-'){x*=10;x+=*ip&15;gc;}
        return f?-x:x;
    }
    int A[MAXN + 5], N, M;
    
    namespace segtree{
    	#define lch (x << 1)
    	#define rch (x << 1 | 1)
    	
    	int le[4*MAXN + 5], ri[4*MAXN + 5]; ll sum[4*MAXN + 5];
    	bool ismx[4*MAXN + 5], ismn[4*MAXN + 5];
    	int mx[4*MAXN + 5], smx[4*MAXN + 5], cmx[4*MAXN + 5];
    	int mn[4*MAXN + 5], smn[4*MAXN + 5], cmn[4*MAXN + 5];
    	int stg[4*MAXN + 5], mxtg[4*MAXN + 5], mntg[4*MAXN + 5];
    	
    	void pushup(int x) {
    		sum[x] = sum[lch] + sum[rch];
    		
    		mx[x] = max(mx[lch], mx[rch]);
    		if( mx[lch] == mx[rch] ) smx[x] = max(smx[lch], smx[rch]), cmx[x] = cmx[lch] + cmx[rch];
    		else if( mx[lch] < mx[rch] ) smx[x] = max(mx[lch], smx[rch]), cmx[x] = cmx[rch];
    		else smx[x] = max(smx[lch], mx[rch]), cmx[x] = cmx[lch];
    		ismx[lch] = (mx[lch] == mx[x]), ismx[rch] = (mx[rch] == mx[x]);
    		
    		mn[x] = min(mn[lch], mn[rch]);
    		if( mn[lch] == mn[rch] ) smn[x] = min(smn[lch], smn[rch]), cmn[x] = cmn[lch] + cmn[rch];
    		else if( mn[lch] > mn[rch] ) smn[x] = min(mn[lch], smn[rch]), cmn[x] = cmn[rch];
    		else smn[x] = min(smn[lch], mn[rch]), cmn[x] = cmn[lch];
    		ismn[lch] = (mn[lch] == mn[x]), ismn[rch] = (mn[rch] == mn[x]);
    	}
    	void maintains(int x, int t) {
    		if( t == 0 ) return ;
    		stg[x] += t, mx[x] += t, mn[x] += t;
    		sum[x] += 1LL * t * (ri[x] - le[x] + 1);
    		if( mn[x] != mx[x] ) smn[x] += t, smx[x] += t;
    	}
    	void maintainmx(int x, int t) {
    		if( mn[x] == mx[x] ) maintains(x, t);
    		else {
    			mxtg[x] += t, sum[x] += 1LL * t * cmx[x];
    			if( mx[x] == smn[x] ) smn[x] += t; mx[x] += t;
    		}
    	}
    	void maintainmn(int x, int t) {
    		if( mn[x] == mx[x] ) maintains(x, t);
    		else {
    			mntg[x] += t, sum[x] += 1LL * t * cmn[x];
    			if( mn[x] == smx[x] ) smx[x] += t; mn[x] += t;
    		}
    	}
    	void pushdown(int x) {
    		if( mxtg[x] ) {
    			if( ismx[lch] ) maintainmx(lch, mxtg[x]);
    			if( ismx[rch] ) maintainmx(rch, mxtg[x]);
    			mxtg[x] = 0;
    		}
    		
    		if( mntg[x] ) {
    			if( ismn[lch] ) maintainmn(lch, mntg[x]);
    			if( ismn[rch] ) maintainmn(rch, mntg[x]);
    			mntg[x] = 0;
    		}
    		
    		if( stg[x] ) maintains(lch, stg[x]), maintains(rch, stg[x]), stg[x] = 0;
    	}
    	void build(int x, int l, int r) {
    		le[x] = l, ri[x] = r, stg[x] = mntg[x] = mxtg[x] = 0;
    		if( l == r ) {
    			sum[x] = mx[x] = mn[x] = A[l], smn[x] = INF, smx[x] = -INF, cmn[x] = cmx[x] = 1;
    			return ;
    		}
    		int m = (l + r) >> 1;
    		build(lch, l, m), build(rch, m + 1, r);
    		pushup(x);
    	}
    	void modifys(int x, int l, int r, int k) {
    		if( l > ri[x] || r < le[x] ) return ;
    		if( l <= le[x] && ri[x] <= r ) {
    			maintains(x, k);
    			return ;
    		}
    		pushdown(x);
    		modifys(lch, l, r, k), modifys(rch, l, r, k);
    		pushup(x);
    	}
    	void modifymn(int x, int l, int r, int k) {
    		if( mx[x] <= k ) return ;
    		if( l > ri[x] || r < le[x] ) return ;
    		if( l <= le[x] && ri[x] <= r && smx[x] < k ) {
    			maintainmx(x, k - mx[x]);
    			return ;
    		}
    		pushdown(x);
    		modifymn(lch, l, r, k), modifymn(rch, l, r, k);
    		pushup(x);
    	}
    	void modifymx(int x, int l, int r, int k) {
    		if( mn[x] >= k ) return ;
    		if( l > ri[x] || r < le[x] ) return ;
    		if( l <= le[x] && ri[x] <= r && smn[x] > k ) {
    			maintainmn(x, k - mn[x]);
    			return ;
    		}
    		pushdown(x);
    		modifymx(lch, l, r, k), modifymx(rch, l, r, k);
    		pushup(x);
    	}
    	ll querys(int x, int l, int r) {
    		if( l > ri[x] || r < le[x] ) return 0;
    		if( l <= le[x] && ri[x] <= r ) return sum[x];
    		pushdown(x); return querys(lch, l, r) + querys(rch, l, r);
    	}
    	int querymn(int x, int l, int r) {
    		if( l > ri[x] || r < le[x] ) return INF;
    		if( l <= le[x] && ri[x] <= r ) return mn[x];
    		pushdown(x); return min(querymn(lch, l, r), querymn(rch, l, r));	
    	}
    	int querymx(int x, int l, int r) {
    		if( l > ri[x] || r < le[x] ) return -INF;
    		if( l <= le[x] && ri[x] <= r ) return mx[x];
    		pushdown(x); return max(querymx(lch, l, r), querymx(rch, l, r));
    	}
    }
    
    void write(int x) {
    	if( x < 0 ) x = -x, putchar('-');
    	if( x >= 10 ) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    void write(ll x) {
    	if( x < 0 ) x = -x, putchar('-');
    	if( x >= 10 ) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    int main() {
    	N = read();
    	for(int i=1;i<=N;i++) A[i] = read();
    	segtree::build(1, 1, N);
    	
    	M = read();
    	for(int i=1;i<=M;i++) {
    		int tp = read(), L = read(), R = read();
    		if( tp <= 3 ) {
    			int X = read();
    			if( tp == 1 ) segtree::modifys(1, L, R, X);
    			else if( tp == 2 ) segtree::modifymx(1, L, R, X);
    			else segtree::modifymn(1, L, R, X);
    		} else {
    			if( tp == 4 ) write(segtree::querys(1, L, R)), puts("");
    			else if( tp == 5 ) write(segtree::querymx(1, L, R)), puts("");
    			else write(segtree::querymn(1, L, R)), puts("");
    		}
    	}
    }
    

    bzoj - 3064:维护标记 max(x + a, b),可以统一题目中的操作,而且可以方便地维护最大值与历史最大值。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    
    const int MAXN = 100000;
    const ll INF = ll(1E12);
    
    struct type{
    	ll a, b; type() {}
    	type(ll _a, ll _b) : a(_a), b(_b) {}
    	friend type operator + (type a, type b) {
    		return type(a.a + b.a, max(a.b + b.a, b.b));
    	} // max(max(x + a.a, a.b) + b.a, b.b)
    	friend type max(type a, type b) {
    		return type(max(a.a, b.a), max(a.b, b.b));
    	} // max(max(x + a.a, a.b), max(x + b.a, b.b))
    }; // max(x + a, b)
    
    int A[MAXN + 5], T;
    namespace segtree{
    	#define lch (x << 1)
    	#define rch (x << 1 | 1)
    	
    	int le[4*MAXN + 5], ri[4*MAXN + 5];
    	type tg[4*MAXN + 5], htg[4*MAXN + 5];
    	type mx[4*MAXN + 5], hmx[4*MAXN + 5];
    	
    	void pushup(int x) {
    		mx[x] = max(mx[lch], mx[rch]), hmx[x] = max(hmx[lch], hmx[rch]);
    	}
    	void maintain(int x, type t, type ht) {
    		hmx[x] = max(hmx[x], mx[x] + ht), mx[x] = mx[x] + t;
    		htg[x] = max(htg[x], tg[x] + ht), tg[x] = tg[x] + t;
    	}
    	void pushdown(int x) {
    		maintain(lch, tg[x], htg[x]);
    		maintain(rch, tg[x], htg[x]);
    		tg[x] = htg[x] = type(0, -INF);
    	}
    	void build(int x, int l, int r) {
    		le[x] = l, ri[x] = r, tg[x] = htg[x] = type(0, -INF);
    		if( l == r ) {
    			mx[x] = hmx[x] = type(-INF, A[l]);
    			return ;
    		}
    		int m = (l + r) >> 1;
    		build(lch, l, m), build(rch, m + 1, r);
    		pushup(x);
    	}
    	type query(int x, int l, int r, int t) {
    		if( l > ri[x] || r < le[x] ) return type(-INF, -INF);
    		if( l <= le[x] && ri[x] <= r ) return (t == 0 ? mx[x] : hmx[x]);
    		pushdown(x); return max(query(lch, l, r, t), query(rch, l, r, t));
    	}
    	void modify(int x, int l, int r, type k) {
    		if( l > ri[x] || r < le[x] ) return ;
    		if( l <= le[x] && ri[x] <= r ) {
    			maintain(x, k, k);
    			return ;
    		}
    		pushdown(x);
    		modify(lch, l, r, k), modify(rch, l, r, k);
    		pushup(x);
    	}
    }
    
    char op[2];
    int main() {
    	scanf("%d", &T);
    	for(int i=1;i<=T;i++) scanf("%d", &A[i]);
    	segtree::build(1, 1, T);
    	
    	int E; scanf("%d", &E);
    	for(int i=1;i<=E;i++) {
    		int X, Y; scanf("%s%d%d", op, &X, &Y);
    		if( op[0] == 'Q' ) {
    			type ans = segtree::query(1, X, Y, 0);
    			printf("%lld
    ", max(ans.a, ans.b));
    		} else if( op[0] == 'A' ) {
    			type ans = segtree::query(1, X, Y, 1);
    			printf("%lld
    ", max(ans.a, ans.b));
    		} else if( op[0] == 'P' ) {
    			int Z; scanf("%d", &Z);
    			segtree::modify(1, X, Y, type(Z, -INF));
    		} else {
    			int Z; scanf("%d", &Z);
    			segtree::modify(1, X, Y, type(-INF, Z));
    		}
    	}
    }
    
  • 相关阅读:
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/12627765.html
Copyright © 2020-2023  润新知