A
直接判断距离能否整除速度
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t; scanf("%d", &t);
while (t--) {
int x, y, a, b; scanf("%d%d%d%d", &x, &y, &a, &b);
if ((y - x) % (a + b))
printf("-1\n");
else
printf("%d\n", (y - x) / (a + b));
}
}
B
需要保留整个字符串,所以对每个字符串判断它的逆序字符串是否存在,存在就配对
最后判断剩下的字符串里面有没有自己是回文串的
#include <bits/stdc++.h>
using namespace std;
map<string, int> vis;
string ans, tmp, incre = "";
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, m; cin >> n >> m;
for (int i = 0; i < n; ++i) {
cin >> tmp;
reverse(tmp.begin(), tmp.end());
if (vis.count(tmp) <= 0 || vis[tmp] <= 0) {
reverse(tmp.begin(), tmp.end());
vis[tmp]++;
}
else {
ans += tmp;
vis[tmp]--;
}
}
for (map<string, int>::iterator res = vis.begin(); res != vis.end(); ++res) {
if (res->second > 0) {
bool flg = true;
tmp = res->first;
for (int i = 0; i < m / 2; ++i) {
if (tmp[i] != tmp[m - i - 1]) {
flg = false;
break;
}
}
if (flg) {
incre = tmp;
break;
}
}
}
cout << ans.size() * 2 + incre.size() << '\n';
cout << ans + incre; reverse(ans.begin(), ans.end());
cout << ans << '\n';
}
C
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 5;
ll t[maxn], l[maxn], h[maxn];
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int q; cin >> q;
for (int i = 0; i < q; ++i) {
int n, m; cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> t[i] >> l[i] >> h[i];
ll L = m, R = m; bool flg = false;
for(int i = 1; i <= n; i++)
{
L = L - (t[i] - t[i - 1]);
R = R + (t[i] - t[i - 1]);
if (R < l[i] || L > h[i]) {
flg = 1;
break;
}
else {
L = max(L, l[i]);
R = min(R, h[i]);
}
}
cout << (flg ? "NO" : "YES") << '\n';
}
return 0;
}
D
考虑一种通用的构造
我们记录出现的>符号个数 c n t cnt cnt,则固定第一个数为 c n t + 1 cnt+1 cnt+1,出现 > > >从第一个数开始减小,但是出现 < < <需要记录个数
我们保证了从 c n t + 1 cnt+1 cnt+1开始递减的序列,要使上升子序列最短,在保证满足 < < <的性质下从大的值开始使用
相同的,在保证 < < <的性质下,从小的开始用就可以使最长
输入:7 >><>><
输出:最短:5 4 3 7 2 1 6,最长:5 4 3 6 2 1 7
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
char a[maxn];
int ans[maxn];
int main()
{
int t; scanf("%d", &t);
while (t--) {
int n; scanf("%d%s", &n, a + 1);
//min
int cnt = 0, l, r, sum;
for (int i = 1; i <= n - 1; ++i) {
if (a[i] == '>')
cnt++;
}
l = cnt, r = n, ans[1] = cnt + 1, sum = 0;
for (int i = 1; i <= n - 1; ++i) {
if (a[i] == '>') {
if (sum) {
for (int j = i; j >= i - sum + 1; --j)
ans[j] = r--;
}
ans[i + 1] = l--;
sum = 0;
}
else sum++;
}
if (sum) {
for (int i = n; i >= n - sum + 1; --i)
ans[i] = r--;
}
for (int i = 1; i <= n; ++i) {
printf("%d%c", ans[i], i == n ? '\n' : ' ');
}
//max
ans[1] = cnt + 1, l = cnt, r = cnt + 2, sum = 0;
for (int i = 1; i <= n - 1; ++i) {
if (a[i] == '>') {
if (sum) {
for (int j = i - sum + 1; j <= i; ++j)
ans[j] = r++;
}
ans[i + 1] = l--;
sum = 0;
}
else sum++;
}
if (sum) {
for (int i = n - sum + 1; i <= n; ++i)
ans[i] = r++;
}
for (int i = 1; i <= n; ++i)
printf("%d%c", ans[i], i == n ? '\n' : ' ');
}
}
E
在树上求给出两点 ( a , b ) (a,b) (a,b)间在 ( x , y ) (x,y) (x,y)之间建立一条边后是否存在经过 k k k条边的路径
注意:同一条边可以多次经过记录贡献
可以发现我们走同一条边来回一次对答案贡献是2,所以我们仅需要判断 k − k- k−路径长度后的答案能不能整除2即可
树上求两点距离可以用 l c a lca lca
存在的路径有
- a → b a\rightarrow b a→b
- a → x → y → b a\rightarrow x\rightarrow y\rightarrow b a→x→y→b
- a → y → x → b a\rightarrow y\rightarrow x\rightarrow b a→y→x→b
- a → x → b a\rightarrow x\rightarrow b a→x→b
- a → y → b a\rightarrow y\rightarrow b a→y→b
注意像 a → x → a → b a\rightarrow x\rightarrow a\rightarrow b a→x→a→b这种存在重复路径的情况是不需要计算的,是包括在是否能整除2这个性质里面
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
vector<int> E[maxn];
int fa[maxn], sz[maxn], son[maxn], dep[maxn], top[maxn];
void dfs(int u, int f) {
sz[u] = 1, fa[u] = f; dep[u] = dep[f] + 1;
for (auto v : E[u]) {
if (v == f) continue;
dfs(v, u);
sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
}
void dfs1(int u, int tf) {
top[u] = tf;
if (!son[u]) return;
dfs1(son[u], tf);
for (auto v : E[u]) {
if (v == fa[u] || v == son[u]) continue;
dfs1(v, v);
}
}
int get_lca(int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
return x;
}
int get_dis(int x, int y) {
if (x > y) swap(x, y);
if (x == y) return 0;
return dep[x] + dep[y] - 2 * dep[get_lca(x, y)];
}
int q, x, y, a, b, k;
bool solve() {
cin >> x >> y >> a >> b >> k;
int dis_xy = get_dis(x, y);
int dis_ab = get_dis(a, b);
int dis_ax = get_dis(a, x);
int dis_ay = get_dis(a, y);
int dis_xb = get_dis(x, b);
int dis_yb = get_dis(y, b);
//cout << "xy=" << dis_xy << ",ab=" << dis_ab << ",ax=" << dis_ax << ",ay=" << dis_ay << ",xb=" << dis_xb << ",yb=" << dis_yb << endl;
if (k >= dis_ab && (k - dis_ab) % 2 == 0)
return true;
if (k >= dis_ax + dis_xy + dis_yb && (k - dis_ax - dis_xy - dis_yb) % 2 == 0)
return true;
if (k >= dis_ax + 1 + dis_yb && (k - dis_ax - 1 - dis_yb) % 2 == 0)
return true;
if (k >= dis_ay + dis_xy + dis_xb && (k - dis_ay - dis_xy - dis_xb) % 2 == 0)
return true;
if (k >= dis_ay + 1 + dis_xb && (k - dis_ay - 1 - dis_xb) % 2 == 0)
return true;
if (k >= dis_ax + dis_xb && (k - dis_ax - dis_xb) % 2 == 0)
return true;
if (k >= dis_ay + dis_yb && (k - dis_ay - dis_yb) % 2 ==0)
return true;
return false;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0);
int n; cin >> n;
for (int i = 1; i < n; ++i) {
int u, v; cin >> u >> v;
E[u].push_back(v);
E[v].push_back(u);
}
dfs(1, 0); dfs1(1, 1);
cin >> q;
while (q--) {
cout << (solve() ? "YES" : "NO") << '\n';
}
}