{

承上篇

这次的代码是好久以前写的

感觉比较乱 将就看看吧

这里介绍线段树的删除和一些其他技巧

以求矩形并的周长和面积为例

}

 

上次讨论了利用线段树解决涂色的问题

有一个问题遗留下来

如果我要擦除颜色 该怎么做呢?

很简单 只要插入颜色为0的线段就可以了

因为这里的插入是覆盖型

任何一个区间只有一个颜色 要擦也是一起擦干净

也就是一个节点上至多只被盖着一条线段 以前的线段会被新来的取代

所以这是一个特殊的问题

更为一般的问题是 一个节点上可以有多条线段 互不干涉 地位平等

在线段树上插入若干这样的线段之后

我们还要执行 删除 统计(测度 连续段数等) 操作

 

先看一个具体问题 PKU 1177

http://poj.org/problem?id=1177

不过 我们把矩形的坐标范围提升至100w 矩形个数为10w

题意很简单 给定若干个矩形 求矩形周长并

先看图

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

为了解决这个问题 我们先把一坨一坨的矩形 进行矩形切割

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

 

我们考虑周长由哪些部分构成

其中 红线是需要统计入周长的竖边 绿线是需要统计入周长的横边

我们称两条蓝线之间的部分为统计区间

我们需要依次统计从左到右的统计区间内的需要计数的矩形边 累加

形象地讲 就是用一根扫描线 从左到右依次扫描

具体实现就是依次遍历那些蓝线然后 累加每个区间的统计结果

  我们任取2个统计区间进行详细讨论 放大前2个统计区间部分

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

考虑为什么同样是矩形边 红边需要统计而深红色的边不需要统计

我们发现深红色的边包含在第一个矩形内部 也就是夹在第一个矩形两条边之间

继续分析 我们可以知道 横边也是这样

深蓝色边加在统计区间内的两条绿色边之间 属于矩形内部 不需要统计

那么 如何判定是否是红边或绿边呢?

我们在扫描线上投下当前经过扫描线矩形的投影

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

 

红边必然造成投影的变化 绿边必然在投影上线段的端点处

没有造成投影变化的竖边 肯定在投影内部 也就是在还未扫描完的矩形内部

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

不在投影线段段端点处的横边 也会夹在在投影线段端点处的两个矩形边内

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

于是 我们将绿边的长度=统计区间宽*投影连续段数*2

再与红边的长度=与上一个区间投影的差求和 即得到当前区间的统计值 再累加即可

[PKU 1177 3277] 线段树(二) {离散化 矩形并问题}

至此 我们只要了解扫描到的矩形的投影的段数N()和总长度M()即可

 

——利用线段树解决这个问题

扫描线从左到右扫描矩形

用线段树记录下扫描线上的投影的情况

当扫描线碰到举行左边的时候就插入这个线段 碰到矩形右边就删除这个线段

用线段树统计出扫描线上的投影的信息

 我们还要重新规划在线段树上的域 除了只有ls[] rs[] l[] r[]需要保留外

我们要添加新的域 覆盖次数cover[] 连续段数ls[] 测度m[](即被覆盖的总长度)

这几个域需要我们实时维护 更需增加维护ls[]的域 lb[] rb[]表示左右端点是否被覆盖

 

介绍一下具体的做法

*事件排序&离散化

 

1 procedure sorty(l,r:longint);
2  var i,j,temp,mid:longint;
3  begin
4 mid:=y[(l+r)shr 1];
5 i:=l; j:=r;
6  repeat
7  while y[i]<mid do inc(i);
8  while mid<y[j] do dec(j);
9  if not(i>j)
10 then begin
11 temp:=y[i];
12 y[i]:=y[j];
13 y[j]:=temp;
14 inc(i); dec(j);
15 end;
16  until i>j;
17  if i<r then sorty(i,r);
18  if l<j then sorty(l,j);
19  end;
20  function find(x:longint):longint;
21  var l,r,mid:longint;
22  begin
23 l:=1; r:=t;
24  while l<=r do
25 begin
26 mid:=(l+r)shr 1;
27 if x<y[mid] then r:=mid-1
28 else if y[mid]<x then l:=mid+1
29 else begin find:=mid; exit; end;
30 end;
31  end;
32  procedure sortindex(l,r:longint);
33  var i,j,temp,mid1,mid2:longint;
34  begin
35 mid1:=index[(l+r)shr 1].x;
36 mid2:=index[(l+r)shr 1].flag;
37 i:=l; j:=r;
38  repeat
39  while (index[i].x<mid1)or((index[i].x=mid1)and(index[i].flag<mid2)) do inc(i);
40  while (mid1<index[j].x)or((mid1=index[j].x)and(mid2<index[j].flag)) do dec(j);
41 if not(i>j)
42 then begin
43 if (index[j].x<index[i].x)or((index[j].x=index[i].x)and(index[j].flag<index[i].flag))
44 then begin
45 temp:=index[i].x;
46 index[i].x:=index[j].x;
47 index[j].x:=temp;
48 temp:=index[i].y1;
49 index[i].y1:=index[j].y1;
50 index[j].y1:=temp;
51 temp:=index[i].y2;
52 index[i].y2:=index[j].y2;
53 index[j].y2:=temp;
54 temp:=index[i].flag;
55 index[i].flag:=index[j].flag;
56 index[j].flag:=temp;
57 end;
58 inc(i); dec(j);
59 end;
60 until i>j;
61 if i<r then sortindex(i,r);
62 if l<j then sortindex(l,j);
63 end;

 

 

 

1 readln(n);
2 t:=0;
3 for i:=1 to n do
4 begin
5 readln(x1[i],y1[i],x2[i],y2[i]);
6 inc(t); y[t]:=y1[i];
7 inc(t); y[t]:=y2[i];
8 end;
9 sorty(1,t);
10 for i:=1 to n do
11 begin
12 y1[i]:=find(y1[i]);
13 y2[i]:=find(y2[i]);
14 end;
15 t:=0;
16 for i:=1 to n do
17 begin
18 inc(t);
19 index[t].x:=x1[i];
20 index[t].y1:=y1[i];
21 index[t].y2:=y2[i];
22 index[t].flag:=-1;
23 inc(t);
24 index[t].x:=x2[i];
25 index[t].y1:=y1[i];
26 index[t].y2:=y2[i];
27 index[t].flag:=1;
28 end;
29 sortindex(1,t);

 

 

  +这是为了能够从左到右扫描

  +由于数据范围有100w 我们需要离散化

    -主程序里1-14行运用快速排序和二分查找将纵坐标坐标离散成数组下标即可

    -排序之后 数组下标可以反映坐标大小 这就是我们需要的离散信息

    -但是我们得记录下原来的值 因为还要统计线段长度

  +称插入或删除一条线段为一个事件 15-29行把所有事件保存起来然后排序

    -注意用flag表示是插入还是删除 如果横坐标相同 先插入后删除

*建树

  +注意建线段树的范围 不是[-100w,100w] 是[0,n]了

*扫描统计

  +插入

 

1 procedure insert(x,a,b:longint);
2 var mid:longint;
3 begin
4 if (a<=tree[x].l)and(tree[x].r<=b)
5 then inc(tree[x].cover)
6 else begin
7 mid:=(tree[x].l+tree[x].r)shr 1;
8 if a<mid then insert(tree[x].lc,a,b);
9 if mid<b then insert(tree[x].rc,a,b);
10 end;
11 if tree[x].cover>0
12 then begin
13 tree[x].m:=y[tree[x].r]-y[tree[x].l];
14 tree[x].lb:=1; tree[x].rb:=1;
15 tree[x].ls:=1;
16 end
17 else if (tree[x].cover=0)and(tree[x].r-tree[x].l=1)
18 then begin
19 tree[x].m:=0;
20 tree[x].lb:=0; tree[x].rb:=0;
21 tree[x].ls:=0;
22 end
23 else begin
24 tree[x].m:=tree[tree[x].lc].m+tree[tree[x].rc].m;
25 tree[x].lb:=tree[tree[x].lc].lb; tree[x].rb:=tree[tree[x].rc].rb;
26 if (tree[tree[x].lc].rb=1)and(tree[tree[x].rc].lb=1)
27 then tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls-1
28 else tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls;
29 end;
30 end;

 

    -(以前的代码 感觉很难看...)

 

    -第4-10行 插入线段的基本语句 具体解释见线段树(一)

    -第11-30行 更新数据域 实质上可以新写一个函数来实现了

      ~前面11-22行判断是否直接赋值

      ~第26-29行分类讨论 lb[] rb[]是否同时为1 判断连续段数的改变

      ~第24行测度直接由儿子更新 求和 25行lb[] rb[]也直接更新即可

  +删除 这里的删除保证以前插入过这条线段

 

1 procedure delete(x,a,b:longint);
2 var mid:longint;
3 begin
4 if (a<=tree[x].l)and(tree[x].r<=b)
5 then dec(tree[x].cover)
6 else begin
7 mid:=(tree[x].l+tree[x].r)shr 1;
8 if a<mid then delete(tree[x].lc,a,b);
9 if mid<b then delete(tree[x].rc,a,b);
10 end;
11 if tree[x].cover>0
12 then begin
13 tree[x].m:=y[tree[x].r]-y[tree[x].l];
14 tree[x].lb:=1; tree[x].rb:=1;
15 tree[x].ls:=1;
16 end
17 else if (tree[x].cover=0)and(tree[x].r-tree[x].l=1)
18 then begin
19 tree[x].m:=0;
20 tree[x].lb:=0; tree[x].rb:=0;
21 tree[x].ls:=0;
22 end
23 else begin
24 tree[x].m:=tree[tree[x].lc].m+tree[tree[x].rc].m;
25 tree[x].lb:=tree[tree[x].lc].lb; tree[x].rb:=tree[tree[x].rc].rb;
26 if (tree[tree[x].lc].rb=1)and(tree[tree[x].rc].lb=1)
27 then tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls-1
28 else tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls;
29 end;
30 end;

 

 

    -所以只要改一改插入

  +统计 根据根节点的测度和连续段数 得出统计值累加

 

1 ans:=0;
2 last:=0;
3 index[t+1].x:=index[t].x;
4 for i:=1 to t do
5 begin
6 if index[i].flag=-1
7 then insert(1,index[i].y1,index[i].y2)
8 else delete(1,index[i].y1,index[i].y2);
9 temp:=index[i+1].x-index[i].x;
10 temp:=temp+temp;
11 temp:=temp*tree[1].ls;
12 temp:=temp+abs(tree[1].m-last);
13 ans:=ans+temp;
14 last:=tree[1].m;
15 end;
16 writeln(ans);

    -运用公式求值

 

这样我们就把求矩形周长并解决了

求矩形面积并更加简单 利用测度即可

问题来源是PKU 3277

两个程序的代码

 

1 {6955221 Master_Chivu 1177 Accepted 1948K 32MS Pascal 4579B 2010-05-24 00:06:55}
2 const maxl=100000;maxn=100000;
3 type
4 treenode=
5 record
6 l,r:longint;
7 ls,lb,rb,m,cover:longint;
8 lc,rc:longint;
9 end;
10 var tree:array[1..maxl shl 1-1]of treenode;
11 x1,x2,y1,y2:array[1..maxn]of longint;
12 y:array[1..maxn shl 1]of longint;
13 index:array[1..maxn shl 1]of record x,y1,y2,flag:longint; end;
14 ans,temp:int64;
15 n,t,i,tot,last:longint;
16 procedure sorty(l,r:longint);
17 var i,j,temp,mid:longint;
18 begin
19 mid:=y[(l+r)shr 1];
20 i:=l; j:=r;
21 repeat
22 while y[i]<mid do inc(i);
23 while mid<y[j] do dec(j);
24 if not(i>j)
25 then begin
26 temp:=y[i];
27 y[i]:=y[j];
28 y[j]:=temp;
29 inc(i); dec(j);
30 end;
31 until i>j;
32 if i<r then sorty(i,r);
33 if l<j then sorty(l,j);
34 end;
35 function find(x:longint):longint;
36 var l,r,mid:longint;
37 begin
38 l:=1; r:=t;
39 while l<=r do
40 begin
41 mid:=(l+r)shr 1;
42 if x<y[mid] then r:=mid-1
43 else if y[mid]<x then l:=mid+1
44 else begin find:=mid; exit; end;
45 end;
46 end;
47 procedure sortindex(l,r:longint);
48 var i,j,temp,mid1,mid2:longint;
49 begin
50 mid1:=index[(l+r)shr 1].x;
51 mid2:=index[(l+r)shr 1].flag;
52 i:=l; j:=r;
53 repeat
54 while (index[i].x<mid1)or((index[i].x=mid1)and(index[i].flag<mid2)) do inc(i);
55 while (mid1<index[j].x)or((mid1=index[j].x)and(mid2<index[j].flag)) do dec(j);
56 if not(i>j)
57 then begin
58 if (index[j].x<index[i].x)or((index[j].x=index[i].x)and(index[j].flag<index[i].flag))
59 then begin
60 temp:=index[i].x;
61 index[i].x:=index[j].x;
62 index[j].x:=temp;
63 temp:=index[i].y1;
64 index[i].y1:=index[j].y1;
65 index[j].y1:=temp;
66 temp:=index[i].y2;
67 index[i].y2:=index[j].y2;
68 index[j].y2:=temp;
69 temp:=index[i].flag;
70 index[i].flag:=index[j].flag;
71 index[j].flag:=temp;
72 end;
73 inc(i); dec(j);
74 end;
75 until i>j;
76 if i<r then sortindex(i,r);
77 if l<j then sortindex(l,j);
78 end;
79 procedure build(a,b:longint);
80 var mid,now:longint;
81 begin
82 inc(tot);
83 now:=tot;
84 tree[now].l:=a;
85 tree[now].r:=b;
86 if b-a>1
87 then begin
88 mid:=(a+b)shr 1;
89 tree[now].lc:=tot+1;
90 build(a,mid);
91 tree[now].rc:=tot+1;
92 build(mid,b);
93 end;
94 end;
95 procedure insert(x,a,b:longint);
96 var mid:longint;
97 begin
98 if (a<=tree[x].l)and(tree[x].r<=b)
99 then inc(tree[x].cover)
100 else begin
101 mid:=(tree[x].l+tree[x].r)shr 1;
102 if a<mid then insert(tree[x].lc,a,b);
103 if mid<b then insert(tree[x].rc,a,b);
104 end;
105 if tree[x].cover>0
106 then begin
107 tree[x].m:=y[tree[x].r]-y[tree[x].l];
108 tree[x].lb:=1; tree[x].rb:=1;
109 tree[x].ls:=1;
110 end
111 else if (tree[x].cover=0)and(tree[x].r-tree[x].l=1)
112 then begin
113 tree[x].m:=0;
114 tree[x].lb:=0; tree[x].rb:=0;
115 tree[x].ls:=0;
116 end
117 else begin
118 tree[x].m:=tree[tree[x].lc].m+tree[tree[x].rc].m;
119 tree[x].lb:=tree[tree[x].lc].lb; tree[x].rb:=tree[tree[x].rc].rb;
120 if (tree[tree[x].lc].rb=1)and(tree[tree[x].rc].lb=1)
121 then tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls-1
122 else tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls;
123 end;
124 end;
125 procedure delete(x,a,b:longint);
126 var mid:longint;
127 begin
128 if (a<=tree[x].l)and(tree[x].r<=b)
129 then dec(tree[x].cover)
130 else begin
131 mid:=(tree[x].l+tree[x].r)shr 1;
132 if a<mid then delete(tree[x].lc,a,b);
133 if mid<b then delete(tree[x].rc,a,b);
134 end;
135 if tree[x].cover>0
136 then begin
137 tree[x].m:=y[tree[x].r]-y[tree[x].l];
138 tree[x].lb:=1; tree[x].rb:=1;
139 tree[x].ls:=1;
140 end
141 else if (tree[x].cover=0)and(tree[x].r-tree[x].l=1)
142 then begin
143 tree[x].m:=0;
144 tree[x].lb:=0; tree[x].rb:=0;
145 tree[x].ls:=0;
146 end
147 else begin
148 tree[x].m:=tree[tree[x].lc].m+tree[tree[x].rc].m;
149 tree[x].lb:=tree[tree[x].lc].lb; tree[x].rb:=tree[tree[x].rc].rb;
150 if (tree[tree[x].lc].rb=1)and(tree[tree[x].rc].lb=1)
151 then tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls-1
152 else tree[x].ls:=tree[tree[x].lc].ls+tree[tree[x].rc].ls;
153 end;
154 end;
155 begin
156 assign(input,'picture.in');
157 reset(input);
158 assign(output,'picture.out');
159 rewrite(output);
160 readln(n);
161 t:=0;
162 for i:=1 to n do
163 begin
164 readln(x1[i],y1[i],x2[i],y2[i]);
165 inc(t); y[t]:=y1[i];
166 inc(t); y[t]:=y2[i];
167 end;
168 sorty(1,t);
169 for i:=1 to n do
170 begin
171 y1[i]:=find(y1[i]);
172 y2[i]:=find(y2[i]);
173 end;
174 t:=0;
175 for i:=1 to n do
176 begin
177 inc(t);
178 index[t].x:=x1[i];
179 index[t].y1:=y1[i];
180 index[t].y2:=y2[i];
181 index[t].flag:=-1;
182 inc(t);
183 index[t].x:=x2[i];
184 index[t].y1:=y1[i];
185 index[t].y2:=y2[i];
186 index[t].flag:=1;
187 end;
188 sortindex(1,t);
189 tot:=0;
190 build(0,t);
191 ans:=0;
192 last:=0;
193 index[t+1].x:=index[t].x;
194 for i:=1 to t do
195 begin
196 if index[i].flag=-1
197 then insert(1,index[i].y1,index[i].y2)
198 else delete(1,index[i].y1,index[i].y2);
199 temp:=index[i+1].x-index[i].x;
200 temp:=temp+temp;
201 temp:=temp*tree[1].ls;
202 temp:=temp+abs(tree[1].m-last);
203 ans:=ans+temp;
204 last:=tree[1].m;
205 end;
206 writeln(ans);
207 close(input);
208 close(output);
209 end.
210
1 {6954141 Master_Chivu 3277 Accepted 4112K 704MS Pascal 3486B 2010-05-23 20:50:27}
2 const maxl=50000; maxn=50000;
3 type
4 treenode=
5 record
6 l,r:longint;
7 cover:longint;
8 lc,rc:longint;
9 end;
10 var tree:array[1..maxl shl 1-1]of treenode;
11 index:array[1..maxn shl 1]of record a,w,flag:longint; end;
12 a,b,w:array[1..maxn]of longint;
13 h:array[0..maxn]of longint;
14 tot,n,i,t:longint; ans,temp:int64;
15 procedure sorth(l,r:longint);
16 var i,j,x,y:longint;
17 begin
18 x:=h[(l+r)shr 1];
19 i:=l; j:=r;
20 repeat
21 while h[i]<x do inc(i);
22 while x<h[j] do dec(j);
23 if not(i>j)
24 then begin
25 y:=h[i];
26 h[i]:=h[j];
27 h[j]:=y;
28 inc(i); dec(j);
29 end;
30 until i>j;
31 if i<r then sorth(i,r);
32 if l<j then sorth(l,j);
33 end;
34 function find(x:longint):longint;
35 var l,r,mid:longint;
36 begin
37 l:=1; r:=n;
38 while l<=r do
39 begin
40 mid:=(l+r)shr 1;
41 if h[mid]<x then l:=mid+1
42 else if h[mid]>x then r:=mid-1
43 else begin find:=mid; exit; end;
44 end;
45 end;
46 procedure sortindex(l,r:longint);
47 var i,j,x1,x2,y:longint;
48 begin
49 x1:=index[(l+r)shr 1].a;
50 x2:=index[(l+r)shr 1].flag;
51 i:=l; j:=r;
52 repeat
53 while (index[i].a<x1)or((index[i].a=x1)and(index[i].flag<x2)) do inc(i);
54 while (x1<index[j].a)or((x1=index[j].a)and(x2<index[j].flag)) do dec(j);
55 if not(i>j)
56 then begin
57 if (index[i].a>index[j].a)
58 or((index[i].a=index[j].a)and(index[i].flag>index[j].flag))
59 then begin
60 y:=index[i].a;
61 index[i].a:=index[j].a;
62 index[j].a:=y;
63 y:=index[i].w;
64 index[i].w:=index[j].w;
65 index[j].w:=y;
66 y:=index[i].flag;
67 index[i].flag:=index[j].flag;
68 index[j].flag:=y;
69 end;
70 inc(i); dec(j);
71 end;
72 until i>j;
73 if i<r then sortindex(i,r);
74 if l<j then sortindex(l,j);
75 end;
76 procedure build(a,b:longint);
77 var mid,now:longint;
78 begin
79 inc(tot);
80 now:=tot;
81 tree[now].l:=a;
82 tree[now].r:=b;
83 if b-a>1
84 then begin
85 mid:=(a+b)shr 1;
86 tree[now].lc:=tot+1;
87 build(a,mid);
88 tree[now].rc:=tot+1;
89 build(mid,b);
90 end;
91 end;
92 procedure insert(x,a,b:longint);
93 var mid:longint;
94 begin
95 if (a<=tree[x].l)and(tree[x].r<=b)
96 then begin
97 inc(tree[x].cover);
98 exit; end;
99 mid:=(tree[x].l+tree[x].r)shr 1;
100 if a<mid then insert(tree[x].lc,a,b);
101 if mid<b then insert(tree[x].rc,a,b);
102 end;
103 procedure delete(x,a,b:longint);
104 var mid:longint;
105 begin
106 if (a<=tree[x].l)and(tree[x].r<=b)
107 then begin
108 dec(tree[x].cover);
109 exit; end;
110 mid:=(tree[x].l+tree[x].r)shr 1;
111 if a<mid then delete(tree[x].lc,a,b);
112 if mid<b then delete(tree[x].rc,a,b);
113 end;
114 function count(x:longint):longint;
115 var ans:longint;
116 begin
117 if tree[x].cover>0
118 then begin
119 count:=h[tree[x].r]-h[tree[x].l];
120 exit; end
121 else begin
122 ans:=0;
123 if tree[x].lc<>0 then ans:=ans+count(tree[x].lc);
124 if tree[x].rc<>0 then ans:=ans+count(tree[x].rc);
125 count:=ans; end;
126 end;
127 begin
128 assign(input,'rectangle.in');
129 reset(input);
130 assign(output,'rectangle.out');
131 rewrite(output);
132 readln(n);
133 for i:=1 to n do
134 begin
135 readln(a[i],b[i],w[i]);
136 h[i]:=w[i];
137 end;
138 sorth(1,n);
139 for i:=1 to n do
140 w[i]:=find(w[i]);
141 t:=0;
142 for i:=1 to n do
143 begin
144 inc(t); index[t].a:=a[i]; index[t].w:=w[i]; index[t].flag:=1;
145 inc(t); index[t].a:=b[i]; index[t].w:=w[i]; index[t].flag:=-1;
146 end;
147 sortindex(1,t);
148 tot:=0;
149 build(0,n);
150 ans:=0;
151 index[t+1].a:=index[t].a;
152 for i:=1 to t do
153 begin
154 if index[i].flag=1
155 then insert(1,0,index[i].w)
156 else delete(1,0,index[i].w);
157 temp:=index[i+1].a-index[i].a;
158 temp:=temp*count(1);
159 ans:=ans+temp;
160 end;
161 writeln(ans);
162 close(input);
163 close(output);
164 end.
165

 

这个问题还是推荐去读一下 陈宏大神的论文

下一篇讨论牛B的Lazy-tag思想

 

Bob HAN 原创 转载请注明出处 http://www.cnblogs.com/Booble/

相关文章:

  • 2021-08-20
  • 2022-12-23
  • 2022-02-10
  • 2021-04-05
  • 2021-12-30
  • 2021-09-07
猜你喜欢
  • 2022-12-23
  • 2021-09-16
  • 2021-07-10
  • 2021-12-25
  • 2022-12-23
  • 2021-08-07
  • 2022-12-23
相关资源
相似解决方案