A. LaIS

设 \(dp_i\) 为到第 i 位的最长的 almost increasing 长度。可以发现,这个 \(dp_i\) 的转移只有从 \(a_j \leq a_i\) 的地方转移过去,或者是找到一个最靠后的 k 使得 \(a_k > a_i\),再从 \([1,k-1]\) 找到一个 j 满足 \(a_j \leq a_i\)。

那么,递推式为

\[dp_i = \max
\begin{cases}
\max\{dp_j\} + 1, &a_j \leq a_i, j \in [1, i-1]
\\
\max\{dp_j\}+2, &a_j \leq a_i, j \in [1, k-1]
\end{cases}
\]

那么可以用一个单调递减的队列来维护并找出 k。用主席树来维护 \(dp\) 数组,下标 \(a_i\) 存值 \(dp_i\)。时间复杂度 \(O(n \log n)\)

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
typedef double db;
typedef long double ld; #define IL inline
#define fi first
#define se second
#define mk make_pair
#define pb push_back
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(), (x).end()
#define dbg1(x) cout << #x << " = " << x << ", "
#define dbg2(x) cout << #x << " = " << x << endl template<typename Tp> IL void read(Tp &x) {
x=0; int f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch == '-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
x *= f;
}
int buf[42];
template<typename Tp> IL void write(Tp x) {
int p = 0;
if(x < 0) { putchar('-'); x=-x;}
if(x == 0) { putchar('0'); return;}
while(x) {
buf[++p] = x % 10;
x /= 10;
}
for(int i=p;i;i--) putchar('0' + buf[i]);
} const int N = 500000 + 5; struct PRETree {
int n, tot;
int rt[N];
int maxv[N << 5], ls[N << 5], rs[N << 5];
void init(int n) {
this -> n = n;
fill(rt, rt + n + 1, 0);
fill(maxv, maxv + (n << 5) + 1, 0);
fill(ls, ls + (n << 5) + 1, 0);
fill(rs, rs + (n << 5) + 1, 0);
}
int newnode() { return ++tot;}
void copynode(int u, int v) {
maxv[u] = maxv[v];
ls[u] = ls[v];
rs[u] = rs[v];
}
int upd(int pre, int L, int R, int pos, int v) {
int o = newnode();
copynode(o, pre);
if(L == R) {
maxv[o] = v;
return o;
}
int M = L+R >> 1;
if(pos <= M) ls[o] = upd(ls[pre], L, M, pos, v);
else rs[o] = upd(rs[pre], M+1, R, pos, v);
maxv[o] = max(maxv[ls[o]], maxv[rs[o]]);
return o;
}
int query(int o, int L, int R, int qL, int qR) {
if(qL <= L && R <= qR) {
return maxv[o];
}
int M = L+R >> 1;
int ans = 0;
if(qL <= M) ans = max(ans, query(ls[o], L, M, qL, qR));
if(M < qR) ans = max(ans, query(rs[o], M+1, R, qL, qR));
return ans;
}
int query_max(int posR, int aR) {
if(posR == 0) return 0;
return query(rt[posR], 1, n, 1, aR);
}
}lpr; int n;
int a[N], dp[N];
int m;
int q[N]; int main() {
#ifdef LOCAL
freopen("A.in", "r", stdin);
#endif
int T; read(T);
while(T--) {
read(n);
lpr.init(n);
m = 0;
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++) {
dp[i] = lpr.query_max(i-1, a[i]) + 1;
if(m >= 1) {
int pos = lower_bound(q+1, q+m+1, i, [&](int x, int y) { return a[x] > a[y];}) - q - 1;
if(pos > 0) {
dp[i] = max(dp[i], lpr.query_max(q[pos]-1, a[i]) + 2);
q[m = pos + 1] = i;
}
else q[m = 1] = i;
}
else {
q[++m] = i;
}
lpr.rt[i] = lpr.upd(lpr.rt[i-1], 1, n, a[i], dp[i]);
}
int ans = 0;
// puts("dp[i] = ");
// for(int i=1;i<=n;i++) {
// dbg1(i); dbg2(dp[i]);
// } for(int i=1;i<=n;i++) ans = max(ans, dp[i]);
printf("%d\n", ans);
}
return 0;
}

G. Hobbits

非常简单的计算几何,模拟的时候为啥没读到?

维护一个最高的点, 然后判断线段是不是在眼睛到最高点这个向量左侧即可。记得判一下平行。

eps 开太小了导致本机能过的数据交上去 WA 了。

#include <bits/stdc++.h>
using namespace std; typedef double db; #define IL inline
#define fi first
#define se second
#define mk make_pair
#define pb push_back
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(), (x).end()
#define dbg1(x) cout << #x << " = " << x << ", "
#define dbg2(x) cout << #x << " = " << x << endl const db eps = 1e-8;
int dcmp(db x) {
if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
} struct P {
db x, y;
P(db x=0.0, db y=0.0):x(x), y(y) {}
}; typedef P V;
IL V operator + (const V& a, const V& b) { return V(a.x + b.x, a.y + b.y);}
IL V operator - (const V& a, const V& b) { return V(a.x - b.x, a.y - b.y);}
IL V operator * (const V& a, db p) { return V(a.x * p, a.y * p);}
IL V operator / (const V& a, db p) { return V(a.x / p, a.y / p);} IL bool operator < (const P& a, const P& b) {
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
IL bool operator == (const P& a, const P& b) {
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}
IL db Dot(const V& a, const V& b) { return a.x * b.x + a.y * b.y;}
IL db Length(const V& a) { return sqrt(Dot(a, a));}
IL db Angle(const V& a, const V& b) { return acos(Dot(a, b) / Length(a) / Length(b));}
IL db Cross(const V& a, const V& b) { return a.x*b.y - a.y*b.x;} IL P GetLineIntersection(P p, V v, P q, V w) {
V u = p-q;
db t = Cross(w, u) / Cross(v, w);
return p + v * t;
} IL bool OnLeft(P a, P b, P p) {
return dcmp(Cross(b - a, p - a)) > 0;
}
IL bool OnSegment(P p, P a1, P a2) {
return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
} const int N = 200000 + 5; int n, H;
P p[N]; int main() {
#ifdef LOCAL
freopen("G.in", "r", stdin);
#endif
scanf("%d%d", &n, &H);
for(int i=1;i<=n;i++) {
int xx, yy; scanf("%d%d", &xx ,&yy);
p[i] = P(xx, yy);
}
p[0] = P(p[n].x, p[n].y + H);
P high = p[n];
db ans = 0.0;
for(int i=n;i>=2;i--) {
if(!OnLeft(p[0], high, p[i])) high = p[i];
V v = p[i-1] - p[i];
if(dcmp(Cross(v, high - p[0])) == 0) { // parallel
if(OnLeft(p[0], high, p[i])) continue;
else ans += Length(v);
continue;
} // not parallel
int b = 2;
P a = GetLineIntersection(p[0], high - p[0], p[i], p[i-1] - p[i]);
if(OnSegment(a, p[i-1], p[i])) {
ans += Length(a - p[i-1]);
}
else {
if(dcmp(Cross(high - p[0], p[i] - p[0])) >= 0 && dcmp(Cross(high - p[0], p[i-1] - p[0])) >= 0) continue;
else ans += Length(p[i] - p[i-1]);
}
}
printf("%.10lf\n", ans);
return 0;
}

H. K and Medians

结论是满足以下两个条件就是 yes。

  • \((k-1) | (n-m)\)
  • 删后的序列中满足一个条件,存在某一个数在删后的序列中且它前面删了 \(\frac{k-1}{2}\) 个数,后面删了 \(\frac{k-1}{2}\) 个数。

以上。

#include <bits/stdc++.h>
using namespace std; const int N = 200000 + 5; int n, k, m;
int a[N]; bool check() {
for(int i=1;i<=m;i++) {
int delL = a[i] - i;
int delR = (n - a[i]) - (m - i);
if(delL >= (k-1) / 2 && delR >= (k-1) / 2) return true;
}
return false;
} int main() {
int T; scanf("%d", &T);
while(T--) {
scanf("%d%d%d", &n, &k, &m);
for(int i=1;i<=m;i++) scanf("%d", a+i);
if((n-m) % (k-1) != 0) { puts("NO"); continue;}
puts(check() ? "YES" : "NO");
}
return 0;
}

I. Plane Tiling

题意:给你两个向量 \(\vec{v_1} = (dx_1, dy_1), \vec{v_2} = (dx_2, dy_2)\) 请恰好选 \(n\) 个不同点 \(p_i = (x_i, y_i)\),使得平面上的所有点都能由下式表示出来。\(P = p_i + a \cdot \vec{v_1} + b \cdot \vec{v_2}\)

做法:先把从 \((0, 0)\) 出发的向量 \(\vec{v_1}, \vec{v_2}\) 构成的平行四边形画出来。接着扩展这个平行四边形,铺满整个平面(可以自行脑补长边贴着长边,短边贴着短边)。然后可以发现整个平面很多点在平行四边形的顶点上。答案其实就等于单个平行四边形内不在平行四边形顶点的点的个数。尝试计算它,可以发现

不在平行四边形顶点上的点的个数 = 平行四边形内部的点的个数 + (平行四边形边上的点的个数 - 4) / 2(注:这里 /2 是因为计算答案的时候只能计算左边和上边。右边和下边会和平面上别的平行四边形算重。减去的是顶点)

引用 pick 定理,可以发现 答案 = 平行四边形面积 - 1 + 1 = 平行四边形面积。(注:这里 +1 是考虑 \((0,0)\) )

所以第一步先判断 \(S = |dx_1 \cdot dy_2 - dx_2 \cdot dy_1|\) 是否等于 \(n\)。如果不等于则无解,反之有解。

法一:接下来可以把平行四边形里面的所有点都输出出来,即平行四边形内部的点和位于上边、左边的点并去掉顶点。记得输出 $(0, 0) $。

法二:再试试分割 \(dx_1, dx_2, dy_1, dy_2\)。设 \(d_x = \gcd (dx_1, dx_2), d_y = \gcd(dy_1, dy_2), m = n / (d_x \cdot d_y)\),那么最后的答案 \(n = m \cdot d_x \cdot d_y\)。

先取 \(x \in [0, d_x), y \in [0, d_y)\) 中的所有点,很显然它们每一个都无法相互表示出来。接下来考虑如何用 \(m\) 去扩展这些点。这一步可以把选出来的点矩阵沿着 \(x\) 轴正向每次平移 \(d_x\) 格共平移 \(m-1\) 次。这个即为答案。

证明:由于 \(a \cdot dy_1 + b \cdot dy_2\) 无法构造出一个 \(y\) 使得 \(0 < y < d_y\),那么我们考虑在 \(a \cdot dy_1 + b \cdot dy_2=0\) 的时候,是否会使得 \(x\) 重选或者漏选。由上式可得 \(a = k \cdot dy_2 / d_y, b = -k \cdot dy_1 / d_y, k \in Z\)。带入 \(x\) 相关式子得

\[x = x_i + k \cdot dy_2 \cdot dx_1 / d_y - k \cdot dy_1 \cdot dx_2 / d_y = x_i + k \cdot S / d_y
\]

而 \(S / d_y = n / d_y = m \cdot d_x\),确实是平移距离。

综上所述,证毕。

最终答案即为 \((i \cdot d_x + r_x, r_y), i \in [0,m), r_x \in [0, d_x), r_y \in [0, d_y)\)

#include <bits/stdc++.h>
using namespace std; typedef long long ll; #define IL inline long long n;
long long dx1, dx2, dy1, dy2; ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b);}
IL ll absl(ll x) { return x < 0 ? -x : x;} int main() {
#ifdef LOCAL
freopen("I.in", "r", stdin);
#endif
scanf("%lld", &n);
scanf("%lld%lld", &dx1, &dy1);
scanf("%lld%lld", &dx2, &dy2);
long long d = absl(dx1 * dy2 - dx2 * dy1);
if(d != n) return puts("NO"), 0;
ll dx = absl(gcd(dx1, dx2)), dy = absl(gcd(dy1, dy2));
ll m = n / dx / dy;
puts("YES");
for(int rx=0;rx<dx;rx++) {
for(int ry=0;ry<dy;ry++) {
for(int i=0;i<m;i++) {
printf("%lld %lld\n", i*dx+rx, 1ll * ry);
}
}
}
return 0;
}

J. Road Reform

先做一次最小生成树,得到最小生成树 T。设做完后最大边权为 \(v\)。

  1. 若 \(v \geq k\),那么由于最小生成树又是最小瓶颈树,那么 \(ans = \sum_{e \in T} (v_e - k)[v_e > k]\)
  2. 若 \(v < k\),那么从非最小生成树边与最小生成树最大边权 \(v\) 中找到离 k 最近的边。

不知道模拟的时候自己在干什么,可能在梦游?

M. Similar Sets

题意:求出二分图中是否存在四元环。若存在,输出四元环在左边集合中的两个点的下标。左边集合大小 \(n \leq 10^5\),右边集合大小 \(m \leq 2 \cdot 10^5\),最坏情况下可能会有 \(2 \cdot 10^5\) 条边。

做法:第一步离散化。再考虑分治。设左边集合中度数大于等于 \(D\) 的点为大点,其余点为小点。枚举每一个左边集合中的点 \(i\),对大点做一种操作,对小点做另一种操作。

  1. 若该点 \(i\) 度数为 \(A\) 大于等于 \(D\),我们看这个点与其他左边集合中其他的点的关系。再设一个 \(w_x\) 数组,若右边集合中下标为 \(x\) 的点与点 \(i\) 相连,这个 \(w_x = 1\),反之 \(w_x = 0\)。这样每次枚举到一个大点,把这个点对应的 \(w_x\) 数组弄出来,然后对左边集合中剩余其他点判断是否有两个 \(w_x\) 为 \(1\)。如果题目想要数据一直不匹配到四元环的话,单次的时间复杂度为 \(O(A + m) = O(m)\)。由于如果找到了四元环可以直接跳出,所以如果数据一直找不到四元环的话,左边集合中的每两个大点,最多只会连接重复的一个右边集合中的点。那么最多只会有 \(O(\frac{m}{D})\) 个大点。那么这一步总体的最坏时间复杂度应为 \(O(\frac{m}{D} \cdot m) = O(\frac{m^2}{D})\)
  2. 若该点 \(i\) 度数为 \(A\) 小于 \(D\),是个小点,由于上一步看过了所有大点和其他所有点的关系,这里看这个点与其他小点的关系即可。接下来我们把点 \(i\) 所连接的所有右边集合中的点组成的点对 \((x,y), x<y\) 推入\(v[x]\) 这个 vector 中。然后枚举完所有小点得到整个 vector 后,再看哪一个 vector 中某个数出现了两次。由于 \(\sum_{i=1}^n A_i = m\) ,时间复杂度应为 \(O(\sum A_i^2[A_i < D])\),根据导数等高中知识,让越多的 \(A_i\) 取到 \(D\) 这个时间复杂度越大,所以最坏时间复杂度为 \(O(D^2 \frac{m}{D}) = O(mD)\)。

最终时间复杂度为 \(O(\frac{m^2}{D} + mD)\),在 \(D = \sqrt{m}\) 时取到较优秀的时间复杂度为 \(O(m \sqrt m)\)

#include<bits/stdc++.h>
using namespace std; typedef long long ll;
typedef double db;
typedef long double ld;
typedef pair<int, int> pii; #define IL inline
#define fi first
#define se second
#define mk make_pair
#define pb push_back
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(), (x).end()
#define dbg1(x) cout << #x << " = " << x << ", "
#define dbg2(x) cout << #x << " = " << x << endl template<typename Tp> IL void read(Tp &x) {
x=0; int f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch == '-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
x *= f;
}
int buf[42];
template<typename Tp> IL void write(Tp x) {
int p = 0;
if(x < 0) { putchar('-'); x=-x;}
if(x == 0) { putchar('0'); return;}
while(x) {
buf[++p] = x % 10;
x /= 10;
}
for(int i=p;i;i--) putchar('0' + buf[i]);
} const int N = 100000 + 5;
const int M = N << 1; int n, m, mm;
int tmp[M];
int pre[M];
int w[M];
vector<int> a[N]; vector<pair<int, int> > mp[M]; void solve() {
mm = 0;
read(n);
for(int i=1;i<=n;i++) {
a[i].clear();
int ki; read(ki);
for(int j=1;j<=ki;j++) {
int x; read(x);
a[i].push_back(x);
tmp[++mm] = x;
}
sort(a[i].begin(), a[i].end());
} sort(tmp+1, tmp+1+mm);
m = unique(tmp+1, tmp+1+mm) - tmp - 1;
for(int i=1;i<=n;i++) {
for(int j=0;j<a[i].size();j++) {
a[i][j] = lower_bound(tmp+1, tmp+1+m, a[i][j]) - tmp;
}
} int sz = sqrt(mm + 0.5); // big -> others
bool ok = false;
for(int i=1;i<=n;i++) {
if(a[i].size() < sz) continue;
for(int j=0;j<a[i].size();j++) w[a[i][j]] = 1;
for(int j=1;j<=n;j++) if(i != j) { if(j < i && a[j].size() >= sz) continue;
int cnt = 0;
for(int k=0;k<a[j].size();k++) {
if(w[a[j][k]]) cnt++;
if(cnt >= 2) { printf("%d %d\n", i, j); ok = true; break;}
}
if(ok) break;
}
for(int j=0;j<a[i].size();j++) w[a[i][j]] = 0;
if(ok) return;
} // small -> small
for(int i=1;i<=n;i++) {
if(a[i].size() >= sz) continue;
for(int j=0;j<a[i].size();j++) {
for(int k=j+1;k<a[i].size();k++) {
mp[a[i][j]].push_back(mk(a[i][k], i));
}
}
} for(int x=1;x<=m;x++) {
for(auto pp : mp[x]) {
int y = pp.first, p = pp.second;
if(pre[y]) {
printf("%d %d\n", p, pre[y]);
ok = true;
break;
}
pre[y] = p;
}
for(auto pp : mp[x]) {
int y = pp.first, p = pp.second;
pre[y] = 0;
}
if(ok) break;
} for(int i=1;i<=m;i++) mp[i].clear();
if(ok) return;
puts("-1");
return;
} int main() {
#ifdef LOCAL
freopen("M.in", "r", stdin);
#endif
int T; read(T);
while(T--) solve();
return 0;
}

2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest AGHIJM 题解的更多相关文章

  1. 2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest

    目录 Contest Info Solutions A. Berstagram B. The Feast and the Bus C. Trip to Saint Petersburg E. The ...

  2. 2019-2020 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules, Teams Preferred)【A题 类型好题】

    A. Berstagram Polycarp recently signed up to a new social network Berstagram. He immediately publish ...

  3. 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules) D. Firecrackers (贪心,二分)

    题意:有个长度为\(n\)的监狱,犯人在位置\(a\),cop在位置\(b\),你每次可以向左或者向右移动一个单位,或者选择不动并在原地放一个爆竹\(i\),爆竹\(i\)在\(s[i]\)秒后爆炸, ...

  4. 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules) C. Berpizza (STL)

    题意:酒吧里有两个服务员,每个人每次都只能服务一名客人,服务员2按照客人进酒吧的顺序服务,服务员3按照客人的钱来服务,询问\(q\),\(1\)表示有客人进入酒吧,带着\(m\)块钱,\(2\)表示询 ...

  5. 2017 ACM - ICPC Asia Ho Chi Minh City Regional Contest

    2017 ACM - ICPC Asia Ho Chi Minh City Regional Contest A - Arranging Wine 题目描述:有\(R\)个红箱和\(W\)个白箱,将这 ...

  6. 2018 ICPC Pacific Northwest Regional Contest I-Inversions 题解

    题目链接: 2018 ICPC Pacific Northwest Regional Contest - I-Inversions 题意 给出一个长度为\(n\)的序列,其中的数字介于0-k之间,为0 ...

  7. 2021 ICPC Gran Premio de Mexico 2da Fecha部分题题解

    前面的水题,在队友的配合下,很快就拿下了,剩下几道大毒瘤题,一直罚座三个小时,好让人自闭...但不得不说,这些题的质量是真的高! H. Haunted House 首先看这个题,大眼一扫,觉得是某种数 ...

  8. 2018-2019 ICPC, NEERC, Southern Subregional Contest

    目录 2018-2019 ICPC, NEERC, Southern Subregional Contest (Codeforces 1070) A.Find a Number(BFS) C.Clou ...

  9. Codeforces 2018-2019 ICPC, NEERC, Southern Subregional Contest

    2018-2019 ICPC, NEERC, Southern Subregional Contest 闲谈: 被操哥和男神带飞的一场ACM,第一把做了这么多题,荣幸成为7题队,虽然比赛的时候频频出锅 ...

  10. ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków

    ACM ICPC Central Europe Regional Contest 2013 Jagiellonian University Kraków Problem A: Rubik’s Rect ...

随机推荐

  1. docker容器资源配额

    1.docker 容器控制CPU docker通过cgroup来控制容器使用的资源限制,可以对docker限制的资源包括cpu.内存.磁盘 1.1 指定docker容器可以使用的cpu份额 # 查看配 ...

  2. Educational Codeforces Round 160 (Rated for Div. 2)

    A 直接模拟,注意细节 #include<bits/stdc++.h> #define ll long long using namespace std; ll p[15] = {1}; ...

  3. 如何通过前后端交互的方式制作Excel报表

    前言 Excel拥有在办公领域最广泛的受众群体,以其强大的数据处理和可视化功能,成了无可替代的工具.它不仅可以呈现数据清晰明了,还能进行数据分析.图表制作和数据透视等操作,为用户提供了全面的数据展示和 ...

  4. Blazor/Hybird 触屏下单程序调优笔记

    环境 Blazor Net8.0 + FreeSql + Bootstrap Blazor 组件 以下都是自己瞎琢磨的和官网资料搬运,肯定有不少错漏和不合理的地方,非常希望各位大佬评论区给我建议和意见 ...

  5. postgresql性能优化3:分区表

    一.分区表产生的背景 随着使用时间的增加,数据库中的数据量也不断增加,因此数据库查询越来越慢. 加速数据库的方法很多,如添加特定的索引,将日志目录换到单独的磁盘分区,调整数据库引擎的参数等.这些方法都 ...

  6. js文字处理两端展示中间省略号

    点击查看代码 function ellipsisText(longText, displayLength) { // 确保显示长度至少包含省略号的3个字符 if (displayLength < ...

  7. c语言编译系统工作原理

    c语言编译系统内部的工作原理 程序生命周期概述 一个程序的生命周期可以被分成四个部分: 创建 编译 运行 退出 以一个简单的 helloworld.c 程序为例: #include<stdio. ...

  8. 5GC 关键技术之网络切片

    目录 文章目录 目录 前文列表 网络切片的需求来自于业务对网络提出的差异化要求 基于 3 大业务场景的切片 基于切片资源访问对象的切片 网络切片的商业价值 网络切片的底层技术支撑 网络切片的粒度 网络 ...

  9. AIRIOT物联网平台助力油库自动化升级 实现业务场景全覆盖

      随着我国石油工业的飞速发展,油库规模迅速扩大,油库系统逐渐完善起来.石油行业属于高风险行业,所以石油化工产品在储存.运输和生产各个环节,均有极高的安监.环保.应急的管理要求.通常情况下,油库容量. ...

  10. 13-flask博客项目之restful api详解1-概念

    一 传统的开发模式 前后端分类概念 前端只需要独立编写客户端代码,后端也只需要独立编写服务端代码提供数据接口即可前端通过AJAX请求来访问后端的数据接口,将Model展示到View中即可 前后端开发者 ...