2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)
2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)
全靠 wxh的博客 补完这套。wxhtxdy!
$f[i][k]$ 表示在第 $i$ 个位置刚好匹配了 $k$ 个字符。转移方程 $$ f[i][k] = \sum_{i - j > h[s[k - 1]]} f[j][k - 1] $$
前缀和优化加滚动就行了。
好像可以直接用 $f[i][k]$ 表示前缀和,就没这么多事了。
#include <bits/stdc++.h> const int N = 1e5 + ;
const int MOD = 1e9 + ; int dp[][N], sum[][N], h[N];
char s[N], t[N]; void M(int &a) {
if (a >= MOD) a -= MOD;
} int main() {
freopen("in.txt", "r", stdin);
int k, n;
scanf("%d%d", &k, &n);
for (int i = ; i < ; i++)
scanf("%d", h + i);
scanf("%s%s", t + , s + );
for (int i = ; i <= n; i++) {
if (s[i] == t[])
dp[][i] = ;
sum[][i] = sum[][i - ] + dp[][i];
}
for (int j = ; j <= k; j++) {
int cur = j & , pre = cur ^ ;
memset(dp[cur], , sizeof(dp[cur]));
memset(sum[cur], , sizeof(sum[cur]));
for (int i = ; i <= n; i++) {
if (s[i] == t[j]) {
int where = i - h[t[j - ] - 'A'] - ;
if (where > )
M(dp[cur][i] += sum[pre][where]);
}
//if (i == 2) printf("%d\n", dp[cur][i]);
M(sum[cur][i] += sum[cur][i - ]);
M(sum[cur][i] += dp[cur][i]);
}
}
printf("%d\n", sum[k & ][n]);
return ;
}
操作顺序对答案无影响,从前往后DP即可。
枚举空位进行DP,$f[i]$ 表示 $i$ 之前已经放好,并且产生了 $i - 1 - cnt[i - 1]$ 个空位的方案数, $g[i]$ 则表示产生了 $i$ 个空位的方案数。
#include <bits/stdc++.h> const int N = 1e6 + ;
const int MOD = 1e9 + ;
int f[N], g[N], cnt[N]; void M(int &a) {
if (a >= MOD) a -= MOD;
} int main() {
int n, m;
scanf("%d%d", &n, &m);
n++;
while (m--) {
int x;
scanf("%d", &x);
cnt[x]++;
}
for (int i = ; i <= n; i++)
cnt[i] += cnt[i - ];
g[] = ;
for (int i = ; i <= n; i++) {
if (cnt[i] == cnt[i - ]) {
if (i - - cnt[i - ] >= )
f[i] = g[i - - cnt[i - ]];
if (i - cnt[i] >= )
M(g[i - cnt[i]] += f[i]);
}
}
printf("%d\n", f[n]);
return ;
}
对于每种颜色能求出其极长链,也就是每次操作两端的端点。
然后操作之间相当于一个拓扑序,对每一种颜色向其链上不同颜色的点连边,拓扑排序即可。
连边需要用倍增优化,就是一次连边只需要连 $logn$ 条边。
#include <bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second const int N = 1e5 + ;
const int M = ;
const int S = N * ; int n, m, color[N], dep[N], degree[S], fa[N][M], id[N][M];
std::vector<int> vec[N], col[N], to[S]; void dfs(int u, int pre = ) {
dep[u] = dep[pre] + ;
fa[u][] = pre;
for (int i = ; i < M; i++)
fa[u][i] = fa[fa[u][i - ]][i - ];
for (int v: vec[u])
if (v != pre)
dfs(v, u);
} int jump(int u, int d) {
for (int i = ; i < M; i++)
if (d >> i & )
u = fa[u][i];
return u;
} int Lca(int u, int v) {
if (dep[u] < dep[v]) std::swap(u, v);
u = jump(u, dep[u] - dep[v]);
if (u == v) return u;
for (int i = M - ; ~i; i--)
if (fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
return fa[u][];
} int dist(int u, int v) {
return dep[u] + dep[v] - * dep[Lca(u, v)];
} int find(int u, int v, int z, int d) {
if (d <= dep[u] - dep[z])
return jump(u, d);
return jump(v, dep[u] + dep[v] - * dep[z] - d);
} void addedge(int color, int u, int v) {
if (dep[u] < dep[v]) std::swap(u, v);
int dif = dep[u] - dep[v];
for (int i = ; i < M; i++)
if (dif >> i & ) {
to[color].push_back(id[u][i]);
u = fa[u][i];
}
if (u == v) {
to[color].push_back(id[u][]);
return;
}
for (int i = M - ; ~i; i--)
if (fa[u][i] != fa[v][i]) {
to[color].push_back(id[u][i]);
to[color].push_back(id[v][i]);
u = fa[u][i];
v = fa[v][i];
}
to[color].push_back(id[u][]);
to[color].push_back(id[v][]);
to[color].push_back(id[fa[u][]][]);
} int X[N], Y[N]; int main() {
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) {
scanf("%d", color + i);
col[color[i]].push_back(i);
}
for (int i = ; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
vec[u].push_back(v);
vec[v].push_back(u);
}
dfs();
int tol = m;
for (int i = ; i < M; i++)
for (int j = ; j <= n; j++)
id[j][i] = ++tol;
for (int i = ; i <= n; i++)
to[id[i][]].push_back(color[i]);
for (int i = ; i < M; i++)
for (int j = ; j <= n; j++)
if (fa[j][i - ]) {
to[id[j][i]].push_back(id[j][i - ]);
to[id[j][i]].push_back(id[fa[j][i - ]][i - ]);
}
for (int i = ; i <= m; i++) {
if (col[i].empty()) {
printf("%d 1 1\n", i);
continue;
}
int x = col[i][], y = col[i][], d = ;
for (int j = ; j < col[i].size(); j++) {
int z = col[i][j], dd;
dd = dist(x, z);
int flag = ;
if (dd > d) {
d = dd;
flag = ;
}
dd = dist(y, z);
if (dd > d) {
d = dd;
flag = ;
}
if (flag == ) {
y = z;
} else if (flag == ) {
x = z;
}
}
X[i] = x; Y[i] = y;
int z = Lca(x, y);
std::vector<std::pii> all;
for (int p: col[i])
all.push_back(std::pii(dist(x, p), p));
std::sort(all.begin(), all.end());
for (int j = ; j < all.size(); j++)
if (all[j].fi != all[j - ].fi + ) {
int u = find(x, y, z, all[j].fi - ), v = find(x, y, z, all[j - ].fi + );
addedge(i, u, v);
}
}
for (int i = ; i <= tol; i++)
for (auto v: to[i])
degree[v]++;
std::queue<int> que;
for (int i = ; i <= tol; i++)
if (!degree[i])
que.push(i);
while (!que.empty()) {
int u = que.front(); que.pop();
if (u <= m && !col[u].empty())
printf("%d %d %d\n", u, X[u], Y[u]);
for (int v: to[u])
if (!--degree[v])
que.push(v);
}
return ;
}
[D - Harry Potter and The Vector Spell]
并查集合并每一列中两个 $1$,不在同一个集合里则对答案贡献为 $1$
#include <bits/stdc++.h> const int N = 1e5 + ; int fa[N]; int getfa(int x) {
return x == fa[x] ? x : fa[x] = getfa(fa[x]);
} std::vector<int> G[N]; int main() {
int n, m;
scanf("%d%d", &m, &n);
for (int i = ; i <= m; i++) {
fa[i] = i;
int k;
scanf("%d", &k);
while (k--) {
int u;
scanf("%d", &u);
G[u].push_back(i);
}
}
int ans = ;
for (int i = ; i <= n; i++) {
if (G[i].size() == ) continue;
if (G[i].size() == ) { ans++; continue; }
int u = G[i][], v = G[i][];
u = getfa(u);
v = getfa(v);
if (u != v) {
ans++;
fa[u] = v;
}
}
printf("%d\n", ans);
}
预处理下每个 major scale 以及其子集。
然后枚举开头和结尾拼起来的是哪个 major scale,中间段再贪心即可。
#include <bits/stdc++.h> std::map<std::string, int> mp;
const int N = 1e7 + ;
int a[N];
bool flag[N];
const int offset[] = {, , , , , , , }; void print(int x) {
for (int i = ; ~i; i--)
printf("%d", x >> i & );
puts("");
} int main() {
std::ios::sync_with_stdio(false); std::cin.tie();
mp["Do"] = ; mp["Do#"] = ;
mp["Re"] = ; mp["Re#"] = ;
mp["Mi"] = ; mp["Fa"] = ;
mp["Fa#"] = ; mp["Sol"] = ;
mp["Sol#"] = ; mp["La"] = ;
mp["La#"] = ; mp["Si"] = ;
for (int i = ; i < ; i++) {
int s = ;
for (int j = ; j < ; j++)
s |= << ((i + offset[j]) % );
flag[s] = ;
}
for (int i = ; i < << ; i++)
for (int j = i; j; j = (j - ) & i)
flag[j] |= flag[i];
int n;
std::cin >> n;
for (int i = ; i <= n; i++) {
std::string str;
std::cin >> str;
a[i] = mp[str];
}
assert(!flag[( << ) - ]);
int ans = n;
for (int i = ; i < ; i++) {
int s = ;
for (int j = ; j < ; j++)
s |= << ((i + offset[j]) % );
int l = , r = n;
while (l <= n && (s >> a[l] & ))
l++;
while (r && (s >> a[r] & ))
r--;
int cur = ;
s = ( << ) - ;
for (int j = l; j <= r; j++) {
if (!flag[s | ( << a[j])]) {
cur++;
s = << a[j];
} else {
s |= << a[j];
}
}
ans = std::min(ans, cur);
}
std::cout << ans << '\n';
return ;
}
贪心地考虑,先把不匹配的 $1$ 从大到小消掉,再把不匹配的 $0$ 从小到大加上。但是如果存在一些匹配了的 $1$ 它们的花费特别大,就不是最优的。
那么就枚举多消去几个已经匹配了的 $1$,这部分肯定也是从大到小优。
用multiset维护即可。
#include <bits/stdc++.h>
#define ll long long const int N = 1e4 + ; std::multiset<ll, std::greater<ll> > st1;
std::multiset<ll> st2;
std::vector<ll> vec;
int n;
ll c[N];
ll sum;
char a[N], b[N]; ll solve(int cnt) {
ll ans = ;
ll s = sum;
if (cnt)
st1.insert(vec[cnt - ]), st2.insert(vec[cnt - ]);
for (auto it: st1) {
s -= it;
ans += s;
}
for (auto it: st2) {
s += it;
ans += s;
}
return ans;
} int main() {
scanf("%d", &n);
for (int i = ; i <= n; i++)
scanf("%lld", c + i);
scanf("%s", a + );
scanf("%s", b + );
for (int i = ; i <= n; i++) {
if (a[i] != b[i]) {
if (a[i] == '') st1.insert(c[i]);
else st2.insert(c[i]);
} else {
if (a[i] == '') vec.push_back(c[i]);
}
if (a[i] == '') sum += c[i];
}
std::sort(vec.begin(), vec.end(), std::greater<ll>());
ll ans = 1e18;
for (int i = ; i <= vec.size(); i++)
ans = std::min(ans, solve(i));
printf("%lld\n", ans);
return ;
}
#include <bits/stdc++.h> #define ll long long const int N = 1e4 + ; struct In {
ll a, t;
bool operator < (const In &rhs) const {
return a > rhs.a;
}
} in[N]; int main() {
int n;
scanf("%d", &n);
for (int i = ; i < n; i++)
scanf("%lld%lld", &in[i].a, &in[i].t);
ll v = ;
double ans1 = ;
for (int i = ; i < n; i++) {
ans1 += v * in[i].t + 0.5 * in[i].a * in[i].t * in[i].t;
v += in[i].a * in[i].t;
}
std::sort(in, in + n);
v = ;
double ans = ;
for (int i = ; i < n; i++) {
ans += v * in[i].t + 0.5 * in[i].a * in[i].t * in[i].t;
v += in[i].a * in[i].t;
}
printf("%.1f\n", ans - ans1);
return ;
}
如果老鼠和猫现在在一条边的两个端点 $(u, v)$ 上,老鼠先走一步到 $w$。
1. 如果老鼠走第二步不回到 $u$,那么猫肯定得跟过去。
2. 如果老鼠第二步走回 $u$,那么猫可以先不走,让老鼠回到 $u$,它再走到 $u$,老鼠走一步到 $w$,猫再跟上,老鼠走一步到 $u$,猫不动,这样就是猫用了 $4$ 步把老鼠在 $u$ 的后继节点 $w$ 给堵住了。
这样的话对每一条边 $(u, v)$ 设为 $(mouse, cat)$。预处理出后继状态以及到终态的最短路。
然后枚举一下老鼠走了几步到达和猫相邻的状态,通过节点深度判断猫是否能到这个状态,可以的话更新答案。
#include <bits/stdc++.h> const int N = 1e5 + ;
const int M = N * ;
const int INF = 0x3f3f3f3f; #define pii pair<int, int>
#define fi first
#define se second std::vector<std::pii> edge, to[M];
std::vector<int> vec[N], temp[M];
int dis[N], dep[N];
int n, mouse; void dfs(int u, int fa) {
for (int v: vec[u]) {
if (v == fa) continue;
dep[v] = dep[u] + ;
dfs(v, u);
}
} int getid(int x, int y) {
return lower_bound(edge.begin(), edge.end(), std::pii(x, y)) - edge.begin();
} int getnext(int u, int no) {
for (int v: vec[u])
if (v != no) return v;
return -;
} int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &mouse);
mouse--;
for (int i = ; i < n; i++)
vec[i].clear(), dep[i] = ;
edge.clear();
for (int i = ; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
u--; v--;
vec[u].push_back(v);
vec[v].push_back(u);
edge.push_back(std::pii(u, v));
edge.push_back(std::pii(v, u));
}
std::sort(edge.begin(), edge.end());
for (int i = ; i < n; i++)
std::reverse(vec[i].begin(), vec[i].end());
if (!~getnext(mouse, -)) {
puts("");
continue;
}
dfs(, -);
for (int i = ; i < n * ; i++)
temp[i].clear();
for (int i = ; i < edge.size(); i++)
dis[i] = INF, to[i].clear();
for (int i = ; i < edge.size(); i++) {
int u = edge[i].fi, v = edge[i].se;
int w = getnext(u, v);
if (!~w) {
dis[i] = ;
temp[].push_back(i);
} else {
to[getid(w, u)].push_back(std::pii(i, ));
if (getnext(w, -) == u)
to[getid(u, w)].push_back(std::pii(i, ));
}
}
for (int i = ; i < n * ; i++)
for (int j: temp[i])
if (dis[j] == i)
for (auto p: to[j])
if (dis[p.fi] > i + p.se) {
dis[p.fi] = i + p.se;
temp[dis[p.fi]].push_back(p.fi);
}
int ans = INF, cur = mouse;
for (int i = ; i < n; i++) {
int ne = getnext(cur, i ? - : );
if (dep[ne] < i || (dep[ne] == i && dep[cur] != i - ))
ans = std::min(ans, i + dis[getid(cur, ne)]);
cur = ne;
}
printf("%d\n", ans);
}
return ;
}
虽说总的状态数是 1 << 30 个,但真正的状态数不会很多,很多状态都无法达到。
所以直接记忆化搜索(抄了wxh的代码,对于位运算部分的处理tql)
#include <bits/stdc++.h> const int N = ; const char s[][N] = {
"",
"",
""
}; std::unordered_map<int, int> mem[N], vis[N];
int n, a[N]; int go(int state, int type, int rotate) {
if (state >> ) return -;
char b[][];
if (!rotate) {
for (int i = ; i < ; ++i)
for (int j = ; j < ; ++j)
b[i][j] = s[i][j + type * ];
} else if (rotate == ) {
for (int i = ; i < ; ++i)
for (int j = ; j < ; ++j)
b[i][j] = s[j][ - i + type * ];
} else if (rotate == ) {
for (int i = ; i < ; ++i)
for (int j = ; j < ; ++j)
b[i][j] = s[ - i][ - j + type * ];
} else {
for (int i = ; i < ; ++i)
for (int j = ; j < ; ++j)
b[i][j] = s[ - j][i + type * ];
}
int p = ;
for (int i = ; ~i; --i) {
bool flag = false;
for (int j = ; j < ; ++j)
for (int k = ; k < ; ++k)
if (b[j][k] == '' && (state >> (i + j) * + k & ))
flag = true;
if (flag) break;
p = i;
}
int new_state = state;
for (int i = ; i < ; ++i)
for (int j = ; j < ; ++j)
if (b[i][j] == '')
new_state |= << (i + p) * + j;
for (int i = ; i < ; ++i)
while ((new_state >> i * & ) == )
new_state = (new_state & ( << * i) - ) | (new_state >> (i + ) * << i * );
return new_state;
} int dfs(int state, int cur) {
if (vis[cur][state] == ) return -;
if (vis[cur][state] == ) return mem[cur][state];
vis[cur][state] = ;
int ans = ;
for (int i = ; i < ; i++) {
int ne = go(state, a[cur], i);
if (~ne) {
int val = dfs(ne, (cur + ) % n);
if (!~val) return -;
ans = std::max(ans, val + );
}
}
vis[cur][state] = ;
mem[cur][state] = ans;
return ans;
} int main() {
scanf("%d", &n);
for (int i = ; i < n; i++)
scanf("%d", a + i);
printf("%d\n", dfs(, ));
return ;
}
三个人的nim...
如果全是 $1$,那么 $n \equiv 0$ (mod $3$)时必输,否则必胜。
如果只有一个不是 $1$,如果 $n \equiv 0$ (mod $3$),第一个人把 非 $1$ 那堆取出 $1$ 就必胜,否则把那一堆取光。
如果有两个不是 $1$,且至少有一个 $2$ 并且 $1$ 的个数不是 $3$ 的倍数,第一个人都可以把一堆取光或者取剩下 $1$ 使得自己赢,否则必败,另外两个人都可以让 $n \equiv 0$ (mod $3$)
如果大于两个,另外两个人的操作空间比第一个人大,就可以让第一个人必败了。
#include <bits/stdc++.h> int main() {
int n;
int cnt1 = , cnt2 = ;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
int x;
scanf("%d", &x);
if (x == ) cnt1++;
else if (x == ) cnt2++;
}
if (cnt1 == n) puts(n % == ? "Lose" : "Win");
else if (cnt1 == n - ) puts("Win");
else if (cnt1 == n - ) puts((cnt2 && cnt1 % != ) ? "Win" : "Lose");
else puts("Lose");
}
对于 $n$ 它的最长上升子序列肯定是 $1$,对于 $n-1$,如果它在 $n$ 后面那么肯定是 $1$,如果在 $n$ 前面那么肯定是 $2$,但是放后面会使得字典序更小。
那么就按最长上升子序列的值排个序。值小的放大的数,同权值的,越靠前面的放越大的数才符合最长上升子序列的值。
#include <bits/stdc++.h> const int N = 1e5 + ; struct In {
int pos, val;
bool operator < (const In &rhs) const {
if (val == rhs.val) return pos < rhs.pos;
return val < rhs.val;
}
} in[N]; int ans[N]; int main() {
int n;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%d", &in[i].val);
in[i].pos = i;
}
std::sort(in + , in + + n);
for (int i = ; i <= n; i++)
ans[in[i].pos] = n - i + ;
for (int i = ; i <= n; i++)
printf("%d%c", ans[i], " \n"[i == n]);
return ;
}
总边数是 $4(n-1)$,至少存在一个点的度数不超过 $3$,那么答案肯定不超过 $3$,并且有一棵树的只割去一条边。
枚举 $A$ 树中每一条边作为割边,在 $B$ 树中这条边连接的两个端点在 $A$ 树中不在一个连通块中,那么这条边需要割掉。
树上启发式合并解决。
#include <bits/stdc++.h>
#define pii pair<int, int> const int N = 1e5 + ; struct Tree {
std::vector<int> G[N];
int son[N], sz[N];
inline void add(int u, int v) {
G[u].push_back(v);
G[v].push_back(u);
}
void dfs(int u, int fa) {
sz[u] = ;
for (auto v: G[u]) {
if (v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
if (sz[son[u]] < sz[v]) son[u] = v;
}
}
} a, b; bool skip[N], color[N];
int cur, n; void cal(int u, const Tree &a) {
color[u] ^= ;
for (auto v: a.G[u])
if (color[v] != color[u]) cur++;
else cur--;
} void edt(int u, int fa, const Tree &a, const Tree &b) {
cal(u, b);
for (auto v: a.G[u])
if (v != fa && !skip[v])
edt(v, u, a, b);
} void dfs(int u, int fa, bool keep, const Tree &a, const Tree &b, std::pii &ans) {
for (auto v: a.G[u])
if (v != fa && v != a.son[u])
dfs(v, u, , a, b, ans);
if (a.son[u])
dfs(a.son[u], u, , a, b, ans), skip[a.son[u]] = ;
edt(u, fa, a, b);
if (fa) {
if (cur < ans.first) ans = std::pii(cur, );
if (ans.first == cur) ans.second++;
}
if (a.son[u]) skip[a.son[u]] = ;
if (!keep)
edt(u, fa, a, b);
} std::pii solve(Tree &a, Tree &b) {
a.dfs(, );
std::pii ans = std::pii(n, );
dfs(, , , a, b, ans);
ans.first++;
return ans;
} int main() {
scanf("%d", &n);
for (int i = ; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
a.add(u, v);
}
for (int i = ; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
b.add(u, v);
}
auto ans = solve(a, b);
if (ans.first == )
return * printf("%d %d\n", , ans.second);
cur = ;
auto res = solve(b, a);
cur = ;
if (ans.first == ) cur += ans.second;
if (res.first == ) cur += res.second;
printf("%d %d\n", , cur);
return ;
}
2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)的更多相关文章
- 2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017) Solution
A:Concerts 题意:给出一个串T, 一个串S,求串S中有多少个串T,可以重复,但是两个字符间的距离要满足给出的数据要求 思路:先顺序统计第一个T中的字符在S中有多少个,然后对于第二位的以及后面 ...
- 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018)
layout: post title: 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 201 ...
- 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018) Solution
A. Numbers Unsolved. B. Broken Watch Solved. 题意: 一个圆盘上,有等分的n块区域,有三根指针,当三根指针分别位于两块区域的交界处时 指针的三点相连会形成一 ...
- Gym 2009-2010 ACM ICPC Southwestern European Regional Programming Contest (SWERC 2009) A. Trick or Treat (三分)
题意:在二维坐标轴上给你一堆点,在x轴上找一个点,使得该点到其他点的最大距离最小. 题解:随便找几个点画个图,不难发现,答案具有凹凸性,有极小值,所以我们直接三分来找即可. 代码: int n; lo ...
- 2016-2017 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2016)
题目链接 Codefores_Gym_101164 Solved 6/11 Penalty Problem A Problem B Problem C Problem D Problem E Pr ...
- 2017-2018 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2017)
A. Cakey McCakeFace 按题意模拟即可. #include<stdio.h> #include<iostream> #include<string.h&g ...
- Southeastern European Regional Programming Contest 2019
easy: I medium-easy: BDEGJ medium: F medium-hard: A A. B. 按 x 排序,\(dp[i][j][k]\) 表示考虑前 \(i\) 个物品,lev ...
- ACM ICPC, Damascus University Collegiate Programming Contest(2018) Solution
A:Martadella Stikes Again 水. #include <bits/stdc++.h> using namespace std; #define ll long lon ...
- 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016)
A. Within Arm's Reach 留坑. B. Bribing Eve 枚举经过$1$号点的所有直线,统计直线右侧的点数,旋转卡壳即可. 时间复杂度$O(n\log n)$. #includ ...
随机推荐
- 我已经看到了,撤回也没用了(PC微信防撤回补丁)
前两天看 GitHub 发现一个有趣的项目,PC微信防撤回补丁,本着研究学习的目的,在看过源码,一顿疯狂操作之后,了解了其原理是基于修改 wechatwin.dll 达到防撤回的. 于是乎,自己动手玩 ...
- OSG :三维无序离散点构建Delaunay三角网
利用OSG的osgUtil库里面的DelaunayTriangulator类. points是需要构建三角网的点 osgUtil::DelaunayTriangulator* trig = new o ...
- CSS属性相关知识
Css选择器 选择器的权重 在css中,哪个选择器的权重高,就走谁的样式. 标签选择器的权重是 1 Class选择器的权重是10 Id选择器的权重是100 行间样式的权重是1000 带有关键字 !im ...
- Spring Security简介与入门Demo
1:Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配 ...
- Spring Boot + Vue 前后端分离开发,权限管理的一点思路
在传统的前后端不分的开发中,权限管理主要通过过滤器或者拦截器来进行(权限管理框架本身也是通过过滤器来实现功能),如果用户不具备某一个角色或者某一个权限,则无法访问某一个页面. 但是在前后端分离中,页面 ...
- Prometheus PromSQL 常用资源
Prometheus PromSQL 常用资源 PromSQL 使用 运算乘:*除:/加:+减:- 函数 sum() 函数:求出找到所有value的值 irate() 函数:统计平均速率 by (标签 ...
- Linux : Nginx相关
nginx安装参考链接: https://www.cnblogs.com/kaid/p/7640723.html 自定义编译目录: https://blog.csdn.net/ainuser/arti ...
- Java 多线程编程——多线程
如果要想在Java之中实现多线程的定义,那么就需要有一个专门的线程主体类进行线程的执行任务的定义,而这个主体类的定义是有要求的,必须实现特定的接口或者继承特定的父类才可以完成. 1. 继承Thread ...
- 配置Java,jdk环境变量
注意:所有的都是配系统变量 变量名:JAVA_HOME 变量值:D:\Program Files\Java\jdk1.8.0_202(以自己的为准)变量名:Path 变量值:%JAVA_HOME%\b ...
- httpclient解析
1.HttpClient简介 HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性,它不仅使客户端发送Http请求变得容易,而且也方便开发人员测试接口(基于Http ...