我同学叫我去打的。
不说了,题还是不错的,但奈何我英语差。。。
不想解释。
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
const ll mod = 998244353;
const int maxn = 100000 + 10;
int main() {
int n, m;
scanf("%d", &n);
string s1, s2;
for (int i = 1; i <= n; i++) cin >> s1;
scanf("%d", &m);
for (int i = 1; i <= m; i++) cin >> s2;
if (n > m) puts("Cuber QQ");
else puts("Quber CC");
return 0;
}
感觉很难,有点难得读,不想看,也不会。
题意:给n个三维点,一个点1能保护另一个点2的条件是, x 1 < = x 2 , y 1 < = y 2 , z 1 < = z 2 x_1<=x_2,y1<=y_2,z_1<=z_2 x1<=x2,y1<=y2,z1<=z2并至少有一维要明确小于。如果一个点没有被保护,就直接死去,叫你看看每个点能存活多久。
我读出来是这样的,但不过我写得能过的代码好像当几个点一样时,有点问题,不想改了,不是很懂,或许数据没有相等?
做法:是不是三维偏序,但不过又和三维偏序不一样,考虑cdq做法,按照 x x x排序,假设 l , m i d l,mid l,mid点的点对处理好了,接下来出了 m i d + 1 , r mid+1,r mid+1,r的点对,首先对于 m i d + 1 , r mid+1,r mid+1,r可以自己处理,我们考虑 l , m i d l,mid l,mid对其的印象,因为第一次排序肯定是 l , m i d l,mid l,mid的 x x x是小于等于 m i d + 1 , r mid+1,r mid+1,r,然后就是对他们可以进行 y y y排序,然后对于前半部分和后半部分,维护一个前缀最大值就可以了(三维偏序好像是前缀和)。
我的前队友秒杀此题 tql
前面的代码写得很丑,因为写炸了。。。
下面放一个好看代码。
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
#define ull unsigned long long
const int maxn = 100000 + 10;
unsigned long long k1, k2;
unsigned long long CoronavirusBeats() {
unsigned long long k3 = k1, k4 = k2;
k1 = k4;
k3 ^= k3 << 23;
k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
return k2 + k4;
}
int n, dp[maxn];
struct node {
ull x, y, z;
int id, flag;
} num[maxn], tmp[maxn];
bool cmp(node a, node b) {
if (a.x == b.x) {
if (a.y == b.y)return a.z < b.z;
return a.y < b.y;
}
return a.x < b.x;
}
bool cmp1(node a, node b) {
return a.y < b.y;
}
int low[maxn];
#define lowbit(x) (x&-x)
void update(int x, int val) {
for (; x < maxn; x += lowbit(x)) low[x] = max(low[x], val);
}
int query(int x) {
int ret = 0;
for (; x; x -= lowbit(x)) ret = max(ret, low[x]);
return ret;
}
void Clear(int x) {
for (; x < maxn; x += lowbit(x)) low[x] = 0;
}
void cdq(int l, int r) {
if (l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid);
int tot = 0;
for (int i = l; i <= mid; i++) {
tmp[++tot] = num[i];
tmp[tot].flag = 0;
}
for (int i = mid + 1; i <= r; i++) {
tmp[++tot] = num[i];
tmp[tot].flag = 1;
}
sort(tmp + 1, tmp + tot + 1, cmp1);
for (int i = 1; i <= tot; i++) {
if (tmp[i].flag == 0) update(tmp[i].z, dp[tmp[i].id]);
else dp[tmp[i].id] = max(dp[tmp[i].id], query(tmp[i].z) + 1);
}
for (int i = 1; i <= tot; i++)
if (tmp[i].flag == 0) Clear(tmp[i].z);
cdq(mid + 1, r);
return;
}
vector<ull> v;
int main() {
cin >> n >> k1 >> k2;
for (int i = 1; i <= n; i++) {
ull x, y, z;
x = CoronavirusBeats();
y = CoronavirusBeats();
z = CoronavirusBeats();
num[i] = node{x, y, z, i};
v.push_back(z);
dp[i] = 1;
}
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end()), v.end());
for (int i = 1; i <= n; i++) {
num[i].z = lower_bound(v.begin(), v.end(), num[i].z) - v.begin() + 1;
}
sort(num + 1, num + 1 + n, cmp);
cdq(1, n);
int ans = 0;
for (int i = 1; i <= n; i++) ans = max(ans, dp[i]);
cout << ans << endl;
for (int i = 1; i <= n; i++) {
cout << dp[i] - 1 << " ";
}
puts("");
return 0;
}
题意:给你一个树,叫你求所有路径中的最大的这个东西 ∏ i ∈ ( u , v ) a i / m \prod_{i\in(u,v)}a_i/m ∏i∈(u,v)ai/m的最小值,其中m是路径的长度,当时我前队友给我说,直接一句点分治。
做法:后来当我看见点权的范围,我瞬间不想做了,哪儿来的什么点分治额。其实也不是很难,假设当一条路径新加入一个点进去,我们会发现原来的式子变成了原来的 m ∗ a i / ( m + 1 ) m*a_i/(m+1) m∗ai/(m+1)这个点权如果是1肯定是变小,如果是2以上,就有变大,当然2也有可能不变,然后思路就有了,维护每个点直接相连的1链的长度,只要次长和最长就可以了,但不过也不好写,我错了好多发,还有些坑。
这里我用的树 dp,首先维护儿子的1的长度,然后再换根。
维护出1的长度,答案就很好求了,每个点的最小值就是 a i / ( l 1 + l 2 + 1 ) a_i/(l1+l2+1) ai/(l1+l2+1)
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
#define ull unsigned long long
const int maxn = 1000000 + 10;
const ll inf = 1e18;
struct edge {
int u, v, nxt;
} ed[maxn << 1];
int head[maxn << 1], cnt;
void add_e(int u, int v) {
ed[++cnt] = edge{u, v, head[u]};
head[u] = cnt;
}
int n, col[maxn], f[maxn][2], s[maxn][2];
void dfs(int u, int fa) {
int mlen1 = 0, s1 = 0, mlen2 = 0, s2 = 0;
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (v == fa) continue;
dfs(v, u);
int k;
if (col[v] == 1) k = 1 + f[v][0];
else k = 0;
if (k > mlen1) {
mlen2 = mlen1;
s2 = s1;
mlen1 = k;
s1 = v;
} else if (k > mlen2) {
mlen2 = k;
s2 = v;
}
}
f[u][0] = mlen1, f[u][1] = mlen2;
s[u][0] = s1, s[u][1] = s2;
}
void dfs1(int u, int fa) {
if (col[fa] == 1) {
int t1 = f[fa][0], son = s[fa][0];
if (son == u) {
t1 = f[fa][1], son = s[fa][1];
}
if (t1 + 1 > f[u][0]) {
f[u][1] = f[u][0];
s[u][1] = s[u][0];
f[u][0] = t1 + 1;
s[u][0] = fa;
} else if (t1 + 1 > f[u][1]) {
f[u][1] = t1 + 1;
s[u][1] = fa;
}
}
for (int i = head[u]; i; i = ed[i].nxt) {
int v = ed[i].v;
if (v != fa) dfs1(v, u);
}
}
int main() {
scanf("%d", &n);
for (int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
add_e(u, v);
add_e(v, u);
}
int mx = 1e9;
for (int i = 1; i <= n; i++) {
scanf("%d", &col[i]);
mx = min(mx, col[i]);
}
// sort(col + 1, col + n + 1);
if (mx == 0) {
printf("0/1\n");
} else if (mx > 1) {
printf("%d/1", mx);
} else {
dfs(1, 0);
dfs1(1, 0);
ll ans1 = col[1], ans2 = f[1][0] + f[1][1] + 1;
for (int i = 2; i <= n; i++) {
if (col[i] > 2) continue;
ll t1 = col[i], t2 = f[i][0] + f[i][1] + 1;
if (t1 * ans2 < t2 * ans1)
ans1 = t1, ans2 = t2;
}
ll g = __gcd(ans1, ans2);
ans1 /= g, ans2 /= g;
printf("%lld/%lld\n", ans1, ans2);
}
return 0;
}
这道题没怎么看,后来听他们说很简单。
题意:给出一个无向图,他不能删除两个点度数都是奇数的变,问最多能删除多少条边,删除是一个动态过程,即如果你删了一条边,这条边的两个节点的度数会减一,给出的图每个点的度数都是偶数。
做法:本人本来就不会什么图论,然后幸好栞过宋聚聚的欧拉回路,然后就知道一个欧拉回路,做法就是找到欧拉回路,然后随便删除一条边,在从两边删除着走就行了。
这道题给差评卡了我,幸好第二天代码公开,学了一写技术。
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define ull unsigned long long
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
const ll mod = 998244353;
const int maxn = 500000 + 10;
struct node {
int u, v, id;
} e[maxn];
vector<pair<int, int> > g[maxn];
int n, m, vis[maxn], sta[maxn], mp[maxn], top;
vector<int> ans;
void dfs(int u) {
mp[u] = 1;
while (SZ(g[u]) != 0) {
pair<int, int> x = g[u][SZ(g[u]) - 1];
g[u].pop_back();
if (vis[x.se]) continue;
vis[x.se] = 1;
dfs(x.fi);
sta[++top] = x.se;
}
}
void Delete(int t) {
int u = e[sta[1]].u, v = e[sta[1]].v;
ans.push_back(sta[1]);
int l = 2, r = t;
while (l < r) {
int tu = e[sta[l]].u, tv = e[sta[l]].v;
if (max(tu, tv) != max(u, v) || min(tu, tv) != min(u, v)) {
ans.push_back(sta[l++]);
if (u == tu) u = tv;
else if (u == tv) u = tu;
if (v == tv) v = tu;
else if (v == tu) v = tv;
} else {
tu = e[sta[r]].u, tv = e[sta[r]].v;
ans.push_back(sta[r--]);
if (u == tu) u = tv;
else if (u == tv) u = tu;
if (v == tv) v = tu;
else if (v == tu) v = tv;
}
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back({v, i});
g[v].push_back({u, i});
e[i] = node{u, v, i};
}
for (int i = 1; i <= n; i++) {
if (mp[i]) continue;
top = 0;
dfs(i);
if (top == 0) continue;
Delete(top);
}
cout << SZ(ans) << endl;
for (auto x:ans) cout << x << " ";
cout << endl;
}
这道题就是叫你求.eoj后缀的字符串个数,而且这个字符串不能是别的字符串的前缀吧。
不解释字符串哈希,怕被卡就双哈希,好像其他算法也能做。
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
#define ull unsigned long long
const ll mod = 998244353;
const int maxn = 100000 + 10;
const ull p = 3145739;
string s[maxn];
ull has[maxn];
unordered_map<ull, int> mp;
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
cin >> s[i];
ull ha1 = 0;
int len = s[i].size();
for (int j = 0; j < len; j++) {
ha1 = ha1 * p + s[i][j];
if (j != len - 1) mp[ha1] = 1;
}
has[i] = ha1;
}
int ans = 0;
for (int i = 0; i < n; i++) {
int len = s[i].size();
if (len < 4) continue;
if (s[i][len - 1] == 'j' && s[i][len - 2] == 'o' && s[i][len - 3] == 'e' && s[i][len - 4] == '.') {
if (mp[has[i]] != 1) {
ans++;
mp[has[i]] = 1;
}
}
}
cout << ans << endl;
return 0;
}
没读,不会。
题意:一个图吧,然后相邻点的点权相差为1 ,叫你染色,点权的范围a到b,这个范围都要染上。
做法:又是图论题,想了想对与一个图只要找到最长链就可以了,在问了问宋聚聚之后是图的直径,好像只有用bfs求,具体看代码吧,写法比较固定。
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define ull unsigned long long
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
const ll mod = 998244353;
const int maxn = 2000 + 10;
const double pi = acos(-1.0);
int n, m, a, b;
vector<int> g[maxn], f;
int vis[maxn], flag, col[maxn];
void dfs(int u, int color) {
vis[u] = color;
f.push_back(u);
for (auto v:g[u]) {
if (flag) return;
if (vis[v] == vis[u]) {
flag = 1;
return;
}
if (vis[v] == 0) dfs(v, -color);
}
}
int dis[maxn];
int bfs(int st, int be) {
for (int i:f) dis[i] = 10000000;
dis[st] = 1;
if (be != -1) col[st] = be;
queue<int> qu;
qu.push(st);
int mx = 0;
while (!qu.empty()) {
int u = qu.front();
qu.pop();
mx = max(mx, dis[u]);
for (auto v:g[u]) {
if (dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
qu.push(v);
if (be != -1) {
col[v] = (col[u] == b) ? col[u] - 1 : col[u] + 1;
}
}
}
}
return mx;
}
int main() {
int _;
for (scanf("%d", &_); _; _--) {
scanf("%d%d%d%d", &n, &m, &a, &b);
for (int i = 0; i <= n; i++) {
vis[i] = 0;
g[i].clear();
}
flag = 0;
for (int i = 1, u, v; i <= m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
if (a >= b) {
if (m != 0) puts("No");
else {
puts("Yes");
for (int i = 1; i <= n; i++) printf("%d ", a);
puts("");
}
continue;
}
int ans = 0;
int now = a;
for (int i = 1; i <= n; i++) {
if (vis[i] != 0) continue;
if (flag == 1) break;
f.clear();
dfs(i, -1);
now = min(a + ans, b);
int vmax = -1, st = 0;
for (int x:f) {
int t = bfs(x, -1);
if (t > vmax) {
vmax = t;
st = x;
}
}
ans += vmax;
bfs(st, now);
}
if (flag || ans < b - a + 1 || b < a) puts("No");
else {
puts("Yes");
for (int i = 1; i <= n; i++) printf("%d ", col[i]);
puts("");
}
}
return 0;
}
不说了,关键是读懂题
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define SZ(x) ((int)(x.size()))
#define all(x) (x).begin(),(x).end()
const ll mod = 998244353;
const int maxn = 100000 + 10;
int main() {
int n, k;
string s = "";
scanf("%d%d", &n, &k);
for (int i = 1; i < k; i++) {
s += 'b';
}
s += 'a';
for (int i = k + 1; i <= n; i++) s += 'd';
cout << s << endl;
return 0;
}