zoukankan      html  css  js  c++  java
  • 【数据结构杂谈】

    简介:

    快要省选了,现在啥也不会的菜鸡最后的挣扎
    这个星期给自己的任务是搞懂网络流数据结构(我才不会说我网络流写累了)
    这个星期的东西都更在这个贴里了

    题目:

    一: [AHOI2009] 维护序列
    [AHOI2009] 维护序列
    代码

    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define mid ((l + r) >> 1)
    
    ll n,cnt,t,mod,a[100005];
    
    struct P{ll l,r,v,lazy1,lazy2;P(){lazy1 = 1;}};
    
    inline int read(){
    	int x=0;
    	char ch=getchar();
    	while(!isdigit(ch))
    	 ch=getchar();
    	while(isdigit(ch))
    	 x=(x<<3)+(x<<1)+(ch^48),
    	  ch=getchar();
    	return x;
    }
    
    struct Segment{
    	P num[(100000) << 2];
    	void up(ll now){num[now].v = (num[num[now].l].v + num[num[now].r].v) % mod;}
    	int build(ll l,ll r){
    		int now = ++cnt;
    		if(l == r){
    			num[now].v = a[l];
    			return now;
    		} 
    		num[now].l = build(l,mid);
    		num[now].r = build(mid + 1,r);
    		up(now);
    		return now;
    	}
    	void push(ll now,ll l,ll r){
    			ll p = num[now].lazy1;
    			ll q = num[now].lazy2;
    			if(num[now].l){
    			num[num[now].l].lazy1 = num[num[now].l].lazy1 * p % mod;
    			num[num[now].l].lazy2 = num[num[now].l].lazy2 * p % mod;
    			num[num[now].l].lazy2 = (num[num[now].l].lazy2 + q) % mod;
    			num[num[now].l].v = (num[num[now].l].v * p + q * (mid - l + 1)) % mod;
    			}			
    			if(num[now].r){
    			num[num[now].r].lazy1 = num[num[now].r].lazy1 * p % mod;
    			num[num[now].r].lazy2 = num[num[now].r].lazy2 * p % mod;
    			num[num[now].r].lazy2 = (num[num[now].r].lazy2 + q) % mod;
    			num[num[now].r].v = (num[num[now].r].v * p + q * (r - mid)) % mod;
    			}
    			num[now].lazy1 = 1;
    			num[now].lazy2 = 0;
    			return;
    	}
    	void change(ll now,ll l,ll r,ll tl,ll tr,ll p,ll q){
    		push(now,l,r);
    		if(tl <= l && r <= tr){
    			num[now].lazy1 = num[now].lazy1 * p % mod;
    			num[now].lazy2 = num[now].lazy2 * p % mod;
    			num[now].lazy2 = (num[now].lazy2 + q) % mod;
    			num[now].v = (num[now].v * p + q * (r - l + 1)) % mod;
    			//std::cout<<l<<" "<<r<<" "<<num[now].v<<std::endl;
    			return;
    		}
    		if(mid >= tl)
    		change(num[now].l,l,mid,tl,tr,p,q);
    		if(mid < tr)
    		change(num[now].r,mid + 1,r,tl,tr,p,q);
    		up(now);
    		return;
    	}
    	ll query(ll now,ll l,ll r,ll tl,ll tr){
    		//std::cout<<l<<" "<<r<<" "<<num[now].lazy1<<" "<<num[now].lazy2<<" "<<num[now].v<<std::endl;		
    		push(now,l,r);
    		ll ans = 0;
    		if(tl <= l && r <= tr)
    		return num[now].v;
    		if(mid >= tl)
    		ans = (ans + query(num[now].l,l,mid,tl,tr)) % mod;
    		if(mid < tr)
    		ans = (ans + query(num[now].r,mid + 1,r,tl,tr)) % mod;
    		return ans;
    	}
    }Q;
    
    
    int main(){
    	n = read(),mod = read();
    	for(int i = 1;i <= n;++i)
    	a[i] = read();
    	Q.build(1,n);
    	t = read();
    	while(t -- ){
    		ll opt,l,r,q;
    		opt = read();
    		if(opt == 1){
    			l = read(),r = read(),q = read();
    			Q.change(1,1,n,l,r,q,0);
    		}
    		if(opt == 2){
    			l = read(),r = read(),q = read();
    			Q.change(1,1,n,l,r,1,q);			
    		}
    		if(opt == 3){
    			l = read(),r = read();
    			std::cout<<Q.query(1,1,n,l,r)<<std::endl;
    		}	
    	}
    }
    

    二:小白逛公园
    维护区间前缀最大,后缀最大,然后合并就行
    查询的时候也可以返回一个线段树类型的东西来信息储存
    代码

    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define mid ((l + r) >> 1)
    
    int n,m,num[500000];
    
    struct P{
    	int l,r,lmax,rmax,ans,sum;
    };
    
    struct Segment{
    	P t[2 * 500005];
    	#define l(a) t[a].l
    	#define r(a) t[a].r
    	#define lm(a) t[a].lmax
    	#define s(a) t[a].sum
    	#define rm(a) t[a].rmax
    	#define ans(a) t[a].ans	
    	int cnt = 0;
    	void up(int now){
    		lm(now) = std::max(lm(l(now)),s(l(now)) + lm(r(now)));
    		rm(now) = std::max(rm(r(now)),s(r(now)) + rm(l(now)));
    		ans(now) = std::max(rm(l(now)) + lm(r(now)),std::max(ans(l(now)),ans(r(now))));
    		s(now) = s(l(now)) + s(r(now));
    	}
    	int build(int l,int r){
    		int now = ++cnt;
    		if(l == r){
    			s(now) = num[l];
    			lm(now) = num[l];
    			rm(now) = num[l];
    			ans(now) = num[l];
    			return now;
    		}
    		else{
    			l(now) = build(l,mid);
    			r(now) = build(mid + 1,r);
    			up(now);
    		}
    		return now;
    	}
    	void change(int l,int r,int to,int p,int now){
    		if(l == r){
    			s(now) = p;
    			lm(now) = p;
    			rm(now) = p;
    			ans(now) = p;
    			return ;		
    		}
    		if(to <= mid)
    		change(l,mid,to,p,l(now));
    		else
    		change(mid + 1,r,to,p,r(now));
    		up(now);
    	}
    	P q(int l,int r,int tl,int tr,int now){
    		if(tl <= l && r <= tr)return t[now];
    		if(tl > mid)
    		return q(mid + 1,r,tl,tr,r(now));
    		if(tr <= mid)
    		return q(l,mid,tl,tr,l(now));
    		P x = q(l,mid,tl,tr,l(now)),y = q(mid + 1,r,tl,tr,r(now)),re;
    		re.sum = x.sum + y.sum;
    		re.lmax = std::max(x.sum + y.lmax,x.lmax);
    		re.rmax = std::max(y.sum + x.rmax,y.rmax);
    		re.ans = std::max(x.ans,std::max(y.ans,x.rmax + y.lmax));
    		return re;
    	}
    }Q;
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i = 1;i <= n;++i)
    	scanf("%d",&num[i]);
    	int q = Q.build(1,n);
    	for(int i = 1;i <= m;++i){
    		int opt,x,y;
    		scanf("%d%d%d",&opt,&x,&y);
    		if(opt == 1){
    			if(x > y)
    			std::swap(x,y);
    			std::cout<<Q.q(1,n,x,y,1).ans<<std::endl;
    		}
    		if(opt == 2){
    			Q.change(1,n,x,y,1);
    		}
    	}
    }//20min写完一发A的感觉真好
    

    三: 【模板】普通平衡树
    不放链接了
    我平衡树,一窍不通
    要恶补
    放一个\(splay\)板子吧
    \(yyb\)的板子真的好,特别优雅)

    #include<iostream>
    #include<cstdio>
    #define ll long long
    
    const int maxn = 500100,INF = 1e9;
    
    int root = 0,N,tot = 0;
    
    struct P{
    	int ch[2];
    	int ff;
    	int cnt;
    	int val;
    	int son;
    }t[maxn];
    
    void push_up(int u){t[u].son= t[t[u].ch[0]].son + t[t[u].ch[1]].son + t[u].cnt;}//维护子树大小
    
    void rotate(int x){//旋转 
    	int y = t[x].ff;
    	int z = t[y].ff;
    	int k = t[y].ch[1] == x;
    	t[z].ch[t[z].ch[1] == y] = x;t[x].ff = z;
    	t[y].ch[k] = t[x].ch[k ^ 1];t[t[x].ch[k ^ 1]].ff = y;
    	t[x].ch[k ^ 1] = y;t[y].ff = x;
    	push_up(y);push_up(x);
    }
    
    void splay(int x,int goal){
    	while(t[x].ff != goal){
    		int y = t[x].ff;
    		int z = t[y].ff;
    		if(z != goal)
    		(t[y].ch[0] == x) ^ (t[z].ch[0] == y) ? rotate(x) : rotate(y);
    		rotate(x); 
    	}
    	if(goal == 0)
    	root = x;
    } 
    
    void insert(int x){
    	int u = root,ff = 0;
    	while(u && t[u].val != x){
    		ff = u;
    		u = t[u].ch[x > t[u].val];
    	}
    	if(u)
    	t[u].cnt ++ ;
    	else{
    		u = ++tot;
    		if(ff)
    		t[ff].ch[x > t[ff].val] = u;
    		t[tot].ch[0] = 0;
    		t[tot].ch[1] = 0;
    		t[tot].ff = ff;
    		t[tot].val = x;
    		t[tot].cnt = 1;
    		t[tot].son = 1;
    	}
    	splay(u,0);
    }
    
    void find(int x){
    	int u = root;
    	if(!u) return;
    	while(t[u].ch[x > t[u].val] && x != t[u].val)
    	u = t[u].ch[x > t[u].val];
    	splay(u,0);
    }
    
    int Next(int x,int f){
    	find(x);
    	int u = root;
    	if((t[u].val > x && f) || (t[u].val < x & !f)) return u;
    	u = t[u].ch[f];
    	while(t[u].ch[f ^ 1]) u = t[u].ch[f ^ 1];
    	return u;
    }
    
    void del(int x){
    	int last = Next(x,0);
    	int next = Next(x,1);
    	splay(last,0);
    	splay(next,last);
    	int del = t[next].ch[0];
    	if(t[del].cnt > 1){
    		t[del].cnt -- ;
    		splay(del,0);
    	}
    	else
    	t[next].ch[0] = 0;
    }
    
    int k_th(int x){
    	int u = root;
    	if(t[u].son < x)
    	return false;
    	while(1){
    		int y = t[u].ch[0];
    		if(x > t[y].son + t[u].cnt){
    			x -= t[y].son + t[u].cnt;
    			u = t[u].ch[1];
    		}
    		else
    		if(t[y].son >= x)
    		u = y;
    		else
    		return t[u].val;
    	}
    }
    
    int main(){
           insert(-2147483647);
           insert(+2147483647);
    	scanf("%d",&N);
    	while(N -- ){
    		int opt;
    		int x;
    		scanf("%d%d",&opt,&x);
    		if(opt == 1)
    		insert(x);
    		if(opt == 2)
    		del(x);
    		if(opt == 3){
    			find(x);
    			std::cout<<t[t[root].ch[0]].son<<std::endl; 
    	    }
    	    if(opt == 4)
    	    std::cout<<k_th(x + 1)<<std::endl;
    	    if(opt == 5)
    	    std::cout<<t[Next(x,0)].val<<std::endl; 
    	    if(opt == 6)
    	    std::cout<<t[Next(x,1)].val<<std::endl; 
    	}
    	return 0;
    }
    

    四:【模板】普通平衡树(数据加强版)
    折磨了我三天左右,还是不会\(splay\),奋斗了两天没有学会\(splay\)\(Dix\)师傅,拿起了\(fhqtreap\),然后我三十分钟做完了

    #include<bits/stdc++.h>
    #define ll long long
    #define A 2000010
    
    inline ll read(){
    	ll ans = 0,f = 1;
    	char a = getchar();
    	while(a != '-' && (a < '0' || a > '9')) a = getchar();
    	if(a == '-') f = -1,a = getchar();
    	while(a <= '9' && a >= '0')
    	ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
    	return f * ans;
    } 
    
    ll ch[A][2],val[A],cv[A],siz[A],cnt;
    #define l(x) ch[x][0]
    #define r(x) ch[x][1]
    #define v(x) val[x]
    #define c(x) cv[x]
    #define s(x) siz[x]
    
    void up(ll x){s(x) = 1 + s(l(x)) + s(r(x));}
    
    ll randoom(){return rand() << 15 | rand();}
    
    ll newcode(ll x){s(++cnt) = 1,v(cnt) = x,c(cnt) = randoom();return cnt;}
    
    void split(ll now,ll k,ll &x,ll &y){
    	if(!now){x = y = 0;return;}
    	if(v(now) <= k) x = now,split(r(now),k,r(now),y);
    	else
    	y = now,split(l(now),k,x,l(now));
    	up(now);
    }
    
    ll merge(ll x,ll y){
    	if(!x || !y)return x + y;
    	if(c(x) < c(y)){
    		r(x) = merge(r(x),y);
    		up(x);return x;
    	}
    	else{
    		l(y) = merge(x,l(y));
    		up(y);return y;
    	}
    }
    
    ll root,x,y,z,cn;
    
    void insert(ll a){
    	cn ++ ;
    	split(root,a,x,y);
    	root = merge(merge(x,newcode(a)),y);
    }
    
    void del(ll a){
    	cn -- ;
    	split(root,a,x,z);
    	split(x,a - 1,x,y);
    	y = merge(l(y),r(y));
    	root = merge(x,merge(y,z));
    }
    
    ll find(ll a){
    	split(root,a - 1,x,y);
    	ll ans = s(x) + 1;
    	root = merge(x,y);
    	return ans;
    }
    
    ll kth(ll now,ll k){
    	if(k <= s(l(now)))return kth(l(now),k);
    	else
    	if(k == s(l(now)) + 1)return now;
    	else
    	return kth(r(now),k - s(l(now)) - 1);
    }
    
    ll pre(ll a){
    	split(root,a - 1,x,y);
    	ll ans = v(kth(x,s(x)));
    	merge(x,y);
    	return ans;
    }
    
    ll nex(ll a){
    	split(root,a,x,y);
    	ll ans = v(kth(y,1));
    	merge(x,y);
    	return ans;
    }
    
    ll n,m;
    ll last,ans;
    
    int main(){
    	n = read(),m = read();
    	for(int i = 1;i <= n;++i){insert(read());}
    	for(int i = 1;i <= m;++i){
    		ll opt = read(),a = read() ^ last;
    		if(opt == 1)
    		insert(a);
    		if(opt == 2)
    		del(a);
    		if(opt == 3)
    		ans ^= (last = find(a));
    		if(opt == 4)
    		ans ^= (last = v(kth(root,a)));
    		if(opt == 5)
    		ans ^= (last = pre(a));
    		if(opt == 6)
    		ans ^= (last = nex(a));
    	}
    	std::cout<<ans<<std::endl;
    }
    


    五: [Ynoi2010] y-fast trie
    [Ynoi2010] y-fast trie
    考虑维护一些最佳匹配\(<x,y>\),\(x + y < c\),我们发现就单纯用\(multiset\)维护这样是\(O(n ^ 2)\)
    我们考虑哪些是不用被记录的,假如有两个这样的匹配\(<x,y>,<y,z>,其中z < x\)那么很显然后者是不用被维护的,那么我们可以通过这个方式
    排除一些不用维护的最佳匹配,那么我们发现最后这样的最佳匹配只会有\(O(n)\)个,最后在最佳匹配和\(S\)中的最大次大值的和的贡献进行比较即可
    所以最后的复杂度是\(O(nlogn)\)

    #include <bits/stdc++.h>
    using namespace std;
    int n,c,sz;
    multiset<int> a,b;
    multiset<int>::iterator it;
    inline int best(int x,int op)
    {
    	if(x==-1) return -1;
    	it=a.upper_bound(c-1-x);
    	if(it==a.begin()) return -1;
    	it--;
    	if(op==1 && *it==x && a.count(x)==1)
    		return (it==a.begin())?-1:*--it;
    	else
    		return *it;
    }
    
    inline void insert(int x)
    {
    	sz++;
    	if(sz==1) { a.insert(x); return; }
    	int y=best(x,0),z=best(y,1),w=best(z,1);
    	if(y!=-1 && z<x)
    	{
    		if(z!=-1 && y==w) b.erase(b.find(y+z));
    		b.insert(x+y);
    	}
    	a.insert(x);
    }
    inline void erase(int x)
    {
    	a.erase(a.find(x)),sz--;
    	if(!sz) return;
    	int y=best(x,0),z=best(y,1),w=best(z,1);
    	if(y!=-1 && z<x)
    	{
    		if(z!=-1 && y==w) b.insert(y+z);
    		b.erase(b.find(x+y));
    	}
    }
    inline int query()
    {
    	it=--a.end();
    	if(a.count(*it)>=2) return *it*2%c;
    	else return (*it+*--it)%c;
    }
    int main()
    {
    	scanf("%d%d",&n,&c);
    	int op,x,lastans=0;
    	while(n--)
    	{
    		scanf("%d%d",&op,&x); x^=lastans;
    		if(op==1) insert(x%c);
            else erase(x%c);
    		if(sz<2) puts("EE"),lastans=0;
    		else printf("%d\n",lastans=max(query(),b.empty()?0:*--b.end()));
    	}
    	return 0;
    }
    

    六:小清新人渣的本愿
    小清新人渣的本愿
    在写上一个题的时候,我觉得如果不强制在线,那么莫队完全可以使用
    于是我在\(Uoj\)问到了这题
    莫队,考虑用\(bitset\)维护是否出现,加减就解决了(可以具体看代码实现)
    那么乘法怎么解决呢,暴力枚举他的约数,不会出问题的\(O(\sqrt{n})\)
    代码(莫队真好写)

    #include<bits/stdc++.h>
    #define ll long long
    
    ll n,m;
    
    std::bitset<100005>f,g,ans;
    
    ll num[100005],rt[100005];
    ll cnt[100005];
    
    struct P{
    	ll l,r,id,x,opt;
    }q[100005];
    
    bool operator < (P a,P b){
    	if(rt[a.l] == rt[b.l])
    	return a.r < b.r;
    	else
    	return rt[a.l] < rt[b.l];
    }
    
    
    void add(ll i){if(cnt[num[i]] ++ == 0)f[num[i]] = 1,g[100005 - num[i]] = 1;}
    void del(ll i){if(cnt[num[i]] -- == 1)f[num[i]] = 0,g[100005 - num[i]] = 0;}
    
    int main(){
    	scanf("%lld%lld",&n,&m);
    	ll s = sqrt(n);
    	for(int i = 1;i <= n;++i)
    	scanf("%lld",&num[i]),rt[i] = (i - 1) / s + 1;
    	for(int i = 1;i <= m;++i){
    		scanf("%lld%lld%lld%lld",&q[i].opt,&q[i].l,&q[i].r,&q[i].x);
    		q[i].id = i;
    	}	
    	std::sort(q + 1,q + m + 1);
    	ll l = 0,r = 0;
    	for(int i = 1;i <= m;++i){
    		while(l < q[i].l)del(l++);
    		while(l > q[i].l)add(--l);
    		while(r < q[i].r)add(++r);
    		while(r > q[i].r)del(r--);
    		if(q[i].opt == 1){
    			if((f & (f << q[i].x)).any())
    			ans[q[i].id] = 1;
    		}
    		if(q[i].opt == 2){
    			if((f & (g >> (100005 - q[i].x))).any())
    			ans[q[i].id] = 1;
    		}
    		if(q[i].opt == 3){
    			for(int j = 1;j * j <= q[i].x;++j){
    				if(!(q[i].x % j))
    				if(f[j] && f[q[i].x / j]){
    					ans[q[i].id] = 1;
    					break;
    				}
    			}
    		}
    	}
    	for(int i = 1;i <= m;++i)
    	ans[i] ? puts("hana") : puts("bi");
    }
    

    七:CF438D The Child and Sequence
    CF438D The Child and Sequence
    三个操作
    区间和
    单点修改
    区间膜
    前两个操作都是平凡的,注意到膜这一部分,做过花神游历各国的都知道\(\sqrt{x}\)这个操作是均摊的,那么对于膜这个操作来说一样是均摊的。
    考虑\(x % p\),那么知这个\(x\)至少减少了一半,所以是\(log\)级别的,我们只需要在线段树上递归时,加上一个操作就是最大值小于\(p\)时便不再做膜即可
    代码

    #include<bits/stdc++.h>
    #define ll long long 
    
    ll n,m;
    ll cnt = 0;
    
    struct Segment{
    	struct P{
    		ll l,r,val,maxx;
    	}t[(100005) << 2];
    	#define l(x) t[x].l
    	#define r(x) t[x].r
    	#define v(x) t[x].val
    	#define ma(x) t[x].maxx
    	#define mid ((l + r) >> 1)
    	void up(ll now){v(now) = v(l(now)) + v(r(now)),ma(now) = std::max(ma(l(now)),ma(r(now)));}
    	ll build(ll l,ll r){
    		ll now = ++ cnt;
    		if(l == r){
    			v(now) = 0;
    			ma(now) = 0;
    			return now;
    		}
    		l(now) = build(l,mid);
    		r(now) = build(mid + 1,r);
    		up(now);
    		return now;
    	}
    	void change(ll now,ll l,ll r,ll p,ll x){
    		 if(l == r){
    		 v(now) = ma(now) = x;
    		 return;	
    		 }
    		 if(p <= mid)
    		 change(l(now),l,mid,p,x);
    		 else
    		 change(r(now),mid + 1,r,p,x);
    		 up(now);
    		 return;
    	}
    	ll q_s(ll now,ll l,ll r,ll nl,ll nr){
    		if(nl <= l && r <= nr)
    		return v(now);
    		ll ans = 0;
    		if(nl <= mid)
    		ans += q_s(l(now),l,mid,nl,nr);
    		if(nr > mid)
    		ans += q_s(r(now),mid + 1,r,nl,nr);
    		return ans;
    	}
    	ll q_m(ll now,ll l,ll r,ll nl,ll nr){
    		if(nl <= l && r <= nr)
    		return ma(now);
    		ll ans = 0;
    		if(nl <= mid)
    		ans = std::max(ans,q_m(l(now),l,mid,nl,nr));
    		if(nr > mid)
    		ans = std::max(ans,q_m(r(now),mid + 1,r,nl,nr));
    		return ans;
    	}
    	void change_mod(ll now,ll l,ll r,ll nl,ll nr,ll m){
    		if(ma(now) < m)
    		return;
    		if(l == r){
    			v(now) %= m;
    			ma(now) %= m;
    			return ;
    		}
    		if(nl <= mid)
    		change_mod(l(now),l,mid,nl,nr,m);
    		if(nr > mid)
    		change_mod(r(now),mid + 1,r,nl,nr,m);
    		up(now);
    	}
    }Q;
    
    int main(){
    	scanf("%lld%lld",&n,&m);
    	ll s = Q.build(1,n);
    	for(int i = 1;i <= n;++i){
    		ll x;
    		scanf("%lld",&x);
    		Q.change(1,1,n,i,x);
    	}
    	for(int i = 1;i <= m;++i){
    		ll opt,l,r,x;
    		scanf("%lld",&opt);
    		if(opt == 1){
    			scanf("%lld%lld",&l,&x);
    			std::cout<<Q.q_s(1,1,n,l,x)<<std::endl;
    		}
    		if(opt == 2){
    			scanf("%lld%lld%lld",&l,&r,&x);
    			if(Q.q_m(1,1,n,l,r) >= x)
    			Q.change_mod(1,1,n,l,r,x) ;
    		}
    		if(opt == 3){
    			scanf("%lld%lld",&l,&x);
    			Q.change(1,1,n,l,x);
    		}
    	}
    }
    
  • 相关阅读:
    大型网站技术架构(八)--网站的安全架构(转)
    大型网站技术架构(七)--网站的可扩展性架构(转)
    大型网站技术架构(六)--网站的伸缩性架构(转)
    大型网站技术架构(五)--网站高可用架构(转)
    大型网站技术架构(四)--网站的高性能架构(转)
    HTML中的空元素
    jetbrains 全家桶,Pycharm激活码,PHPStorm激活码,WebStorm激活码,Goland激活码,Clion激活码,intellij idea激活码(亲测可用)
    legend3---22、通过html,可以使php、vue、jquery、js达成完美的配合
    IlluminateDatabaseQueryException : SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes
    template cannot be keyed. Place the key on real elements instead.
  • 原文地址:https://www.cnblogs.com/dixiao/p/14476809.html
Copyright © 2011-2022 走看看