https://loj.ac/problem/2722

题解

考场上想了60分,但是由于自己不知道在怎么zz,我连那个ai<bi都没看到,误以为出题人没给lca不相同的部分分,然后觉得lca不同的部分想出来了要是相出lca相同的不就肝过去了……最后剩下的想法就是……为啥没给lca不同的呢……是我想错了???

剩了一个小时写暴力好像当时已经精神失常了,算了不想说了

出了考场写了一下60分,细节真是多到让我吐了,我代码能力疯狂下降吗,写了60分就370行了 出题人大毒瘤啊

从头到尾说一下部分分

前20给枚举链求链交的\(n^2\)暴力

再15分,似乎可以线段树,但是我归到S1的部分了

再15分c=0,可以枚举一个公共lca,求两个最小的v值,可以线段树合并,在lca处删除

再15分,就是相交部分是一条链的,这个枚举树上的每个点作为公共lca,然后我们就发现是

两条链的价值-代价 - 链交部分的价值

而链交部分的价值,就是这这个点深度 - 两条链中较低点lca的深度

忽略到枚举的点是常数

就是val1 - dis[lca1] + val2 或者 val2 - dis[lca2] + val1中的最大值即可,如果选了深度较小lca会被更新

直接线段树合并维护就好

猫锟卡乱搞了,大家散了吧

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <ctime>
#include <map>
#include <set>
#define fi first
#define se second
#define pii pair<int,int>
//#define ivorysi
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 50005
using namespace std;
typedef long long int64;
typedef double db;
typedef unsigned int u32;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9' ) {
res = res * 10 - '0' + c;
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct node {
int to,next;int64 val;
}E[MAXN * 2];
struct qry_node {
int u,v,lca;int64 val;
}qry[MAXN * 2];
int M,N,sumE,head[MAXN],fa[MAXN],dep[MAXN],pos[MAXN],st[MAXN * 2][20],idx,len[MAXN * 2],cnt;
int64 dis[MAXN],ans;
bool all_zero,all_lca_1,all_lca_distinct;
bool has[MAXN];
void add(int u,int v,int64 c) {
E[++sumE].to = v;
E[sumE].next = head[u];
E[sumE].val = c;
head[u] = sumE;
}
int min_dep(int a,int b) {
return dep[a] < dep[b] ? a : b;
}
int max_dep(int a,int b) {
return dep[a] > dep[b] ? a : b;
}
int lca(int a,int b) {
a = pos[a];b = pos[b];
if(a > b) swap(a,b);
int l = len[b - a + 1];
return min_dep(st[a][l],st[b - (1 << l) + 1][l]);
}
int64 Dist(int a,int b) {
return dis[a] + dis[b] - 2 * dis[lca(a,b)];
}
void dfs(int u) {
dep[u] = dep[fa[u]] + 1;
st[++idx][0] = u;
pos[u] = idx;
for(int i = head[u] ;i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u]) {
fa[v] = u;
dis[v] = dis[u] + E[i].val;
dfs(v);
st[++idx][0] = u;
}
}
}
void Init() {
sumE = 0;idx = 0;ans = -1e18;
all_zero = 1;all_lca_1 = 1;all_lca_distinct = 1;
memset(has,0,sizeof(has));
for(int i = 1 ; i <= N ; ++i) head[i] = 0;
read(N);
int a,b;int64 c;
for(int i = 1 ; i < N ; ++i) {
read(a);read(b);read(c);
add(a,b,c);add(b,a,c);
if(c != 0) all_zero = 0;
}
dfs(1);
for(int j = 1 ; j <= 19 ; ++j) {
for(int i = 1 ; i <= idx ; ++i) {
if(i + (1 << j) - 1 > idx) break;
st[i][j] = min_dep(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);
}
}
read(M);
for(int i = 1 ; i <= M ; ++i) {
read(a);read(b);read(c);
qry[i].u = a;qry[i].v = b;qry[i].lca = lca(a,b);
qry[i].val = Dist(a,b) - c;
if(has[qry[i].lca]) all_lca_distinct = 0;
if(qry[i].lca != 1) all_lca_1 = 0;
has[qry[i].lca] = 1;
}
}
namespace task1 {
void Solve() {
for(int i = 1 ; i <= M ; ++i) {
for(int j = 1 ; j <= M ; ++j) {
if(i == j) continue;
if(dep[qry[i].lca] < dep[qry[j].lca]) continue;
int u = max_dep(qry[i].lca,lca(qry[i].u,qry[j].u));
int v = max_dep(qry[i].lca,lca(qry[i].v,qry[j].v));
if(u == v) {
u = max_dep(qry[i].lca,lca(qry[i].u,qry[j].v));
v = max_dep(qry[i].lca,lca(qry[i].v,qry[j].u));
}
if(u != v) {
ans = max(ans,qry[i].val + qry[j].val - Dist(u,v));
}
}
} }
int check() {
for(int i = 1 ; i <= M ; ++i) {
for(int j = 1 ; j <= M ; ++j) {
if(i == j) continue;
if(dep[qry[i].lca] < dep[qry[j].lca]) continue;
int u = max_dep(qry[i].lca,lca(qry[i].u,qry[j].u));
int v = max_dep(qry[i].lca,lca(qry[i].v,qry[j].v));
if(u == v) {
u = max_dep(qry[i].lca,lca(qry[i].u,qry[j].v));
v = max_dep(qry[i].lca,lca(qry[i].v,qry[j].u));
}
if(u != v) {
if(ans == qry[i].val + qry[j].val - Dist(u,v)) {
out(i);space;out(j);enter;
}
}
}
}
}
};
namespace task2 {
struct tr_node {
int lc,rc;
int64 maxa,maxb;
}tr[MAXN * 40];
int Ncnt,rt[MAXN];
vector<int> st[MAXN],ed[MAXN];
bool cmp(qry_node a,qry_node b) {
return a.v < b.v;
}
void update(int u) {
int64 la,lb,ra,rb;
la = lb = ra = rb = -2e18;
if(tr[u].lc) {
la = tr[tr[u].lc].maxa;lb = tr[tr[u].lc].maxb;
}
if(tr[u].rc) {
ra = tr[tr[u].rc].maxa;rb = tr[tr[u].rc].maxb;
}
tr[u].maxa = max(la,ra);
tr[u].maxb = max(lb,rb);
}
int Merge(int u,int v,int64 val) {
if(!u) return v;
if(!v) return u;
pii t[2] = {mp(tr[u].lc,tr[v].rc),mp(tr[u].rc,tr[v].lc)};
for(int i = 0 ; i <= 1 ; ++i) {
int a = t[i].fi,b = t[i].se;
if(!a || !b) continue;
ans = max(tr[a].maxa + tr[b].maxb + val,ans);
ans = max(tr[a].maxb + tr[b].maxa + val,ans);
}
tr[u].lc = Merge(tr[u].lc,tr[v].lc,val);
tr[u].rc = Merge(tr[u].rc,tr[v].rc,val); if(!tr[u].lc && !tr[u].rc) {
tr[u].maxa = max(tr[u].maxa,tr[v].maxa);
tr[u].maxb = max(tr[u].maxb,tr[v].maxb);
}
else update(u);
return u;
}
void Insert(int &u,int L,int R,int pos,int64 va,int64 vb,bool on,int64 val) {
if(!u) {
u = ++Ncnt;
tr[u].lc = tr[u].rc = 0;
tr[u].maxa = tr[u].maxb = -2e18;
}
if(L == R) {
if(on) {
tr[u].maxa = va;tr[u].maxb = vb;
}
else {
tr[u].maxa = max(tr[u].maxa,va);
tr[u].maxb = max(tr[u].maxb,vb);
}
return;
}
int mid = (L + R) >> 1;
if(pos <= mid) {
Insert(tr[u].lc,L,mid,pos,va,vb,on,val);
if(tr[u].rc) {
ans = max(va + tr[tr[u].rc].maxb + val,ans);
ans = max(vb + tr[tr[u].rc].maxa + val,ans);
}
}
else {
Insert(tr[u].rc,mid + 1,R,pos,va,vb,on,val);
if(tr[u].lc) {
ans = max(va + tr[tr[u].lc].maxb + val,ans);
ans = max(vb + tr[tr[u].lc].maxa + val,ans);
}
} update(u);
}
void dfs(int u) {
int s = st[u].size();
int64 ma,mb;
for(int i = 0 ; i < s ; ++i) {
int id = st[u][i];
if(dep[qry[id].lca] < dep[u]) {
Insert(rt[u],1,N,dep[qry[id].lca],qry[id].val,qry[id].val + dis[qry[id].lca],0,-dis[u]);
}
}
int64 tmp = -1e18;
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u]) {
dfs(v);
if(rt[v]) Insert(rt[v],1,N,dep[u],-2e18,-2e18,1,-dis[u]);
rt[u] = Merge(rt[u],rt[v],-dis[u]);
}
}
ans = max(ans,tmp);
if(dep[N] == N) {
int s = ed[u].size();
int64 v = 2e18;
for(int i = 0 ; i < s ; ++i) {
int id = ed[u][i];
if(qry[id].u == qry[id].v) continue;
ans = max(ans,qry[id].val - v);
int64 t = -qry[id].val + 2 * (dis[qry[id].v] - dis[qry[id].u]);
v = min(v,t);
}
}
}
void Solve() {
Ncnt = 0;
for(int i = 1 ; i <= N ; ++i) {
rt[i] = 0;st[i].clear();ed[i].clear();
}
for(int i = 1 ; i <= M ; ++i) {
if(qry[i].u > qry[i].v) swap(qry[i].u,qry[i].v);
}
sort(qry + 1,qry + M + 1,cmp);
for(int i = 1 ; i <= M ; ++i) {
st[qry[i].u].pb(i);
st[qry[i].v].pb(i);
ed[qry[i].lca].pb(i);
}
dfs(1);
}
};
namespace task3 {
vector<int> st[MAXN],ed[MAXN];
struct tr_node {
int lc,rc;
int64 v,s;
}tr[MAXN * 40];
int rt[MAXN],Ncnt;
void update(int u) {
int64 lv,rv;
lv = rv = -2e18;tr[u].s = -1e18;
if(tr[u].lc) {lv = tr[tr[u].lc].v;tr[u].s = max(tr[u].s,tr[tr[u].lc].s);}
if(tr[u].rc) {rv = tr[tr[u].rc].v;tr[u].s = max(tr[u].s,tr[tr[u].rc].s);}
tr[u].v = max(lv,rv);
tr[u].s = max(tr[u].s,lv + rv);
}
int Merge(int u,int v) {
if(!u) return v;
if(!v) return u;
tr[u].lc = Merge(tr[u].lc,tr[v].lc);
tr[u].rc = Merge(tr[u].rc,tr[v].rc);
if(tr[u].lc || tr[u].rc) update(u);
return u;
}
void Insert(int &u,int L,int R,int pos,int64 v) {
if(!u) {
u = ++Ncnt;
tr[u].lc = tr[u].rc = 0;tr[u].v = -2e18;
tr[u].s = -1e18;
}
if(L == R) {
tr[u].v = v;return;
}
int mid = (L + R) >> 1;
if(pos <= mid) Insert(tr[u].lc,L,mid,pos,v);
else Insert(tr[u].rc,mid + 1,R,pos,v);
update(u);
}
void dfs(int u) {
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u]) {
dfs(v);
rt[u] = Merge(rt[u],rt[v]);
}
}
int s = st[u].size();
for(int i = 0 ; i < s ; ++i) {
int id = st[u][i];
if(dep[qry[id].lca] < dep[u]) {
Insert(rt[u],1,M,id,qry[id].val);
}
}
s = ed[u].size();
for(int i = 0 ; i < s ; ++i) {
int id = ed[u][i];
Insert(rt[u],1,M,id,-2e18);
}
if(rt[u]) {
ans = max(ans,tr[rt[u]].s);
} }
void Solve() {
Ncnt = 0;
for(int i = 1 ; i <= N ; ++i) {
st[i].clear();ed[i].clear();rt[i] = 0;
}
for(int i = 1 ; i <= M ; ++i) {
st[qry[i].u].pb(i);
st[qry[i].v].pb(i);
ed[qry[i].lca].pb(i);
}
dfs(1);
}
};
namespace task4 {
vector<int> st[MAXN];
pii C[MAXN];
int64 V[MAXN * 4];
int f[MAXN * 4],cnt;
int64 get_dist(int a,int b) {
return Dist(f[a],f[b]) + V[a] + V[b];
}
void Merge(pii &path,int p) {
if(!p) return;
if(!path.se) path.se = p;
else if(!path.fi) path.fi = p;
else {
int64 x1 = get_dist(p,path.fi),x2 = get_dist(p,path.se),x3 = get_dist(path.fi,path.se);
if(x1 >= max(x2,x3)) {
path = mp(p,path.fi);
}
else if(x2 > max(x1,x3)) {
path = mp(p,path.se);
}
}
}
void dfs(int u) {
int s = st[u].size();
C[u] = mp(0,0);
if(u != 1) {
for(int i = 0 ; i < s ; ++i) {
Merge(C[u],st[u][i]);
if(C[u].fi && C[u].se) {
ans = max(ans,get_dist(C[u].fi,C[u].se) / 2 - dis[u]);
}
}
}
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u]) {
dfs(v);
int t1[2] = {C[u].fi,C[u].se};
int t2[2] = {C[v].fi,C[v].se};
if(u != 1) {
for(int j = 0 ; j <= 1 ; ++j) {
for(int k = 0 ; k <= 1 ; ++k) {
int s = t1[j],t = t2[k];
if(!s || !t) continue;
ans = max(ans,get_dist(s,t) / 2 - dis[u]);
}
}
}
Merge(C[u],C[v].fi);Merge(C[u],C[v].se);
}
}
}
void Solve() {
for(int i = 1 ; i <= N ; ++i) {
st[i].clear();
}
cnt = 0;
for(int i = 1 ; i <= M ; ++i) {
qry[i].val = -qry[i].val + Dist(qry[i].u,qry[i].v);
V[++cnt] = Dist(qry[i].u,qry[i].v) - 2 * qry[i].val + dis[qry[i].u];
f[cnt] = qry[i].v;
st[qry[i].u].pb(cnt);
V[++cnt] = Dist(qry[i].u,qry[i].v) - 2 * qry[i].val + dis[qry[i].v];
f[cnt] = qry[i].u;
st[qry[i].v].pb(cnt);
}
dfs(1);
}
};
namespace task5 {
vector<pii > st[MAXN];
map<int,pii > dp[MAXN];
int64 V[MAXN * 4];
int f[MAXN * 4],cnt;
int64 get_dist(int a,int b) {
return Dist(f[a],f[b]) + V[a] + V[b];
}
void Merge(pii &path,int p) {
if(!p) return;
if(!path.se) path.se = p;
else if(!path.fi) path.fi = p;
else {
int64 x1 = get_dist(p,path.fi),x2 = get_dist(p,path.se),x3 = get_dist(path.fi,path.se);
if(x1 >= max(x2,x3)) {
path = mp(p,path.fi);
}
else if(x2 > max(x1,x3)) {
path = mp(p,path.se);
}
}
}
void dfs(int u) {
int s = st[u].size();
for(int i = 0 ; i < s ; ++i) {
pii t = st[u][i];
if(!dp[u].count(t.se)) {
dp[u][t.se] = mp(0,0);
}
Merge(dp[u][t.se],t.fi);
if(dp[u][t.se].fi && dp[u][t.se].se) { ans = max(ans,get_dist(dp[u][t.se].fi,dp[u][t.se].se) / 2 - dis[u] + dis[t.se]);
}
}
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(v != fa[u]) {
dfs(v);
if(dp[v].size() > dp[u].size()) swap(dp[u],dp[v]);
map<int,pii >::iterator it = dp[v].begin();
while(it != dp[v].end()) {
if(u != it->fi && dp[u].count(it->fi)) {
int t1[2] = {dp[u][it->fi].fi,dp[u][it->fi].se};
int t2[2] = {dp[v][it->fi].fi,dp[v][it->fi].se};
for(int j = 0 ; j <= 1 ; ++j) {
for(int k = 0 ; k <= 1 ; ++k) {
int s = t1[j],t = t2[k];
if(!s || !t) continue;
ans = max(ans,get_dist(s,t) / 2 - dis[u] + dis[it->fi]); }
}
Merge(dp[u][it->fi],it->se.fi);
Merge(dp[u][it->fi],it->se.se);
}
else {
dp[u][it->fi] = it->se;
}
++it;
}
dp[v].clear();
}
}
dp[u].erase(u);
}
void Solve() {
cnt = 0;
for(int i = 1 ; i <= N ; ++i) {
st[i].clear();dp[i].clear();
}
for(int i = 1 ; i <= M ; ++i) {
qry[i].val = -qry[i].val + Dist(qry[i].u,qry[i].v);
V[++cnt] = Dist(qry[i].u,qry[i].v) - 2 * qry[i].val + dis[qry[i].u] - dis[qry[i].lca];
f[cnt] = qry[i].v;
if(qry[i].u != qry[i].lca) st[qry[i].u].pb(mp(cnt,qry[i].lca));
V[++cnt] = Dist(qry[i].u,qry[i].v) - 2 * qry[i].val + dis[qry[i].v] - dis[qry[i].lca];
f[cnt] = qry[i].u;
if(qry[i].v != qry[i].lca) st[qry[i].v].pb(mp(cnt,qry[i].lca));
}
dfs(1);
}
};
int main() {
#ifdef ivorysi
freopen("center4.in","r",stdin);
#else
freopen("center.in","r",stdin);
freopen("center.out","w",stdout);
#endif
for(int i = 2 ; i <= 100000 ; ++i) len[i] = len[i / 2] + 1;
int T;
read(T);
cnt = 0;
while(T--) {
Init();
if(M <= 300) task1::Solve();
else if(all_lca_1) task4::Solve();
else if(dep[N] == N) task2::Solve();
else if(all_zero) task3::Solve();
else if(all_lca_distinct) task2::Solve();
else {
task2::Solve();
task5::Solve();
} if(ans <= -1e18) puts("F");
else {out(ans);enter;}
}
return 0;
}

直接调用task2和task5可以通过,然鹅我分部分分写的话直接用……task2处理一条链上同时所有lca为1的路径似乎有问题?懒得debug了= =

12.8K写得我真的非常开心

再20分的话,就非常神仙了

有个性质是链并的两倍等于两条链长 + u1 u2距离 + v1 v2距离

这时候再沿用前面思路的话就非常鸽

我们拆个式子

枚举u1和u2的lca是r

然后答案就是

dis[u_1] + dis[u_2] - 2 * dis[r] + (1链长价值 - 代价) - (2链长价值 - 代价) + dist(v1,v2)

我们多个附加点p1连向v1,边权是链长价值-代价 + dis[u_1]

当遇到u_1 的时候,加进去p_1,就相当于对于一个形态固定的树,加进去一个点可使用,找两个点集中各一个点的一条最长链

因为只有增加操作,那么两个点集中的各一个端点必然是两个点集中各自最长链的端点

最后20分,只要做一遍S1,再记录一下lca做一下S2,数组启发式合并就行……

我代码写的好长

NOI考完,我想我知道

我大概是LN的绝望了

【LOJ】#2722. 「NOI2018」情报中心的更多相关文章

  1. LOJ2722 「NOI2018」情报中心

    「NOI2018」情报中心 题目描述 C 国和D 国近年来战火纷飞. 最近,C 国成功地渗透进入了D 国的一个城市.这个城市可以抽象成一张有$n$ 个节点,节点之间由$n - 1$ 条双向的边连接的无 ...

  2. LOJ #2721. 「NOI2018」屠龙勇士(set + exgcd)

    题意 LOJ #2721. 「NOI2018」屠龙勇士 题解 首先假设每条龙都可以打死,每次拿到的剑攻击力为 \(ATK\) . 这个需要支持每次插入一个数,查找比一个 \(\le\) 数最大的数(或 ...

  3. loj#2718. 「NOI2018」归程

    题目链接 loj#2718. 「NOI2018」归程 题解 按照高度做克鲁斯卡尔重构树 那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离 s ...

  4. loj#2721. 「NOI2018」屠龙勇士

    题目链接 loj#2721. 「NOI2018」屠龙勇士 题解 首先可以列出线性方程组 方程组转化为在模p意义下的同余方程 因为不保证pp 互素,考虑扩展中国剩余定理合并 方程组是带系数的,我们要做的 ...

  5. Loj #2719. 「NOI2018」冒泡排序

    Loj #2719. 「NOI2018」冒泡排序 题目描述 最近,小 S 对冒泡排序产生了浓厚的兴趣.为了问题简单,小 S 只研究对 *\(1\) 到 \(n\) 的排列*的冒泡排序. 下面是对冒泡排 ...

  6. loj#2720. 「NOI2018」你的名字

    链接大合集: loj uoj luogu bzoj 单纯地纪念一下写的第一份5K代码.../躺尸 因为ZJOI都不会所以只好写NOI的题了... 总之字符串题肯定一上来就拼个大字符串跑后缀数组啦! ( ...

  7. loj 2719 「NOI2018」冒泡排序 - 组合数学

    题目传送门 传送门 题目大意 (相信大家都知道) 显然要考虑一个排列$p$合法的充要条件. 考虑这样一个构造$p$的过程.设排列$p^{-1}_{i}$满足$p_{p^{-1}_i} = i$. 初始 ...

  8. LOJ #2718. 「NOI2018」归程 Dijkstra+可持久化并查集

    把 $Noi2018$ day1t1 想出来还是挺开心的,虽然是一道水题~ 预处理出来 1 号点到其它点的最短路,然后预处理边权从大到小排序后加入前 $i$ 个边的并查集. 这个并查集用可持久化线段树 ...

  9. LOJ 2721 「NOI2018」屠龙勇士——扩展中国剩余定理

    题目:https://loj.ac/problem/2721 1.注意别一输入 p[ i ] 就 a[ i ] %= p[ i ] ,因为在 multiset 里找的时候还需要真实值. 2.注意用 m ...

随机推荐

  1. bzoj千题计划134:bzoj3124: [Sdoi2013]直径

    http://www.lydsy.com/JudgeOnline/problem.php?id=3124 第一问: dfs1.dfs2 dfs2中记录dis[i]表示点i距离最长链左端点的距离 第二问 ...

  2. lvm--pv丢失后恢复

    [root@db-backup ~]# vgcfgrestore vg_backup  Couldn't find device with uuid JgYDQu-R1AG-wrD2-AHpX-A14 ...

  3. python 常用对linux系统文件及目录的操作

    目录 1.取得当前目录——os.getcwd() >>> import os >>> s=os.getcwd()#获得当前运行脚本所在目录 >>> ...

  4. JQuery的选择器对控件ID含有特殊字符的解决方法-涨姿势了!

    1.jquery类库在我们实际项目中用的很多,大家经常需要根据控件的id,获取对应的html元素. 但是:当id含有特殊字符的时候,是不能选中的. 2. 自己简单的测试了下,jquery的id选择器只 ...

  5. 20155207 2016-2017-2 《Java程序设计》第七周学习总结

    20155207 2016-2017-2 <Java程序设计>第七周学习总结 教材学习内容总结 第13章 时间与日期 13.1 认识时间与日期 13.1.1 时间的度量 格林威治时间(GM ...

  6. [NOI导刊2010提高&洛谷P1774]最接近神的人 题解(树状数组求逆序对)

    [NOI导刊2010提高&洛谷P1774]最接近神的人 Description 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某 ...

  7. POJ 2485 Highways( 最小生成树)

    题目链接 Description The islandnation of Flatopia is perfectly flat. Unfortunately, Flatopia has no publ ...

  8. 防止 Google Smart Lock 记忆错的用户名

    默认 chrome 会查找密码上面的那个(非隐藏非禁用)的表单域 如果上面是个短信验证码框,就会将验证码当成用户名提示用户保存. 在用户名 input 上添加 autocomplete="u ...

  9. python+selenium初学者常见问题处理

    要做web自动化,第一件事情就是搭建自动化测试环境,那就没法避免的要用到selenium了. 那在搭建环境和使用过程中经常会遇到以下几类问题: 1.引入selenium包失败: 出现这种错误,一般分为 ...

  10. Redis简介——(一)

    1.关于关系型数据库和nosql数据库 关系型数据库是基于关系表的数据库,最终会将数据持久化到磁盘上,而nosql数据 库是基于特殊的结构,并将数据存储到内存的数据库.从性能上而言,nosql数据库 ...