ACM-ICPC 2018 沈阳赛区网络预赛
Contents
A. Gudako and Ritsuka
留坑。
B. Call of Accepted
题意:
定义了一种新的运算符
思路:
先中缀转后缀,然后考虑如何最大如何最小,按题意模拟即可。
Code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
char s[110];
ll suffix[110];
int vis[110];
unordered_map<char, int> mp;
inline void Init() {
mp.clear();
mp['('] = 0;
mp['+'] = 1;
mp['-'] = 1;
mp['*'] = 2;
mp['d'] = 3;
}
stack<char> symbol;
stack<ll> Min, Max;
inline void Run() {
Init();
while (scanf("%s", s) != EOF) {
while (!symbol.empty()) symbol.pop();
while (!Min.empty()) Min.pop();
while (!Max.empty()) Max.pop();
memset(vis, 0, sizeof vis);
int cnt = 0;
for (int i = 0, len = strlen(s); i < len; ++i) {
if (isdigit(s[i])) {
ll tmp = 0;
int flag = 1;
if (i == 1 && s[0] == '-')
symbol.pop(), flag = -1;
else if (i > 1 && s[i - 1] == '-' && s[i - 2] == '(')
symbol.pop(), flag = -1;
for (; i < len && isdigit(s[i]); ++i) {
tmp = tmp * 10 + s[i] - '0';
}
suffix[++cnt] = tmp * flag;
--i;
} else {
if (symbol.empty())
symbol.emplace(s[i]);
else if (s[i] == '(')
symbol.emplace(s[i]);
else if (s[i] == ')') {
while (1) {
int top = symbol.top();
symbol.pop();
if (top == '(')
break;
suffix[++cnt] = top;
vis[cnt] = 1;
}
} else {
while (!symbol.empty() && mp[symbol.top()] >= mp[s[i]]) {
suffix[++cnt] = symbol.top();
symbol.pop();
vis[cnt] = 1;
}
symbol.emplace(s[i]);
}
}
}
while (!symbol.empty()) {
suffix[++cnt] = symbol.top();
symbol.pop();
vis[cnt] = 1;
}
for (int i = 1; i <= cnt; ++i) {
if (!vis[i]) {
Min.emplace(suffix[i]);
Max.emplace(suffix[i]);
} else {
ll top1 = Min.top();
Min.pop();
ll top2 = Min.top();
Min.pop();
ll top3 = Max.top();
Max.pop();
ll top4 = Max.top();
Max.pop();
if (suffix[i] == '+') {
Min.emplace(top1 + top2);
Max.emplace(top3 + top4);
} else if (suffix[i] == '-') {
Min.emplace(top2 - top3);
Max.emplace(top4 - top1);
} else if (suffix[i] == '*') {
ll ansmin = top2 * top1;
ansmin = min(ansmin, top2 * top3);
ansmin = min(ansmin, top4 * top1);
ansmin = min(ansmin, top4 * top3);
ll ansmax = top2 * top1;
ansmax = max(ansmax, top2 * top3);
ansmax = max(ansmax, top4 * top1);
ansmax = max(ansmax, top4 * top3);
Min.emplace(ansmin);
Max.emplace(ansmax);
} else {
Min.emplace(top2);
Max.emplace(top3 * top4);
}
}
}
printf("%lld %lld\n", Min.top(), Max.top());
}
}
int main() {
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif
Run();
return 0;
}
C. Convex Hull
留坑。
D. Made In Heaven
题意:
找第
思路:
A* 算法。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
#define N 1005
#define M 50005
int n, m, k;
ll T;
bool vis[N];
int d[N];
struct node {
int v;
int cost;
node() {}
node(int v, ll cost) : v(v), cost(cost) {}
inline bool operator<(const node &b) const {
return cost + d[v] > b.cost + d[b.v];
}
} edge[M], revedge[M];
struct Edge {
int v, cost;
inline Edge() {}
inline Edge(int v, int cost) : v(v), cost(cost) {}
};
vector<Edge> E[N], revE[N];
inline void Dijstra(int st) {
memset(vis, false, sizeof vis);
for (int i = 1; i <= n; ++i) {
d[i] = INF;
}
priority_queue<node> q;
d[st] = 0;
q.push(node(st, 0));
while (!q.empty()) {
node tmp = q.top();
q.pop();
int u = tmp.v;
if (vis[u])
continue;
vis[u] = true;
int len = E[u].size();
for (int i = 0; i < len; ++i) {
int v = E[u][i].v;
int cost = E[u][i].cost;
if (!vis[v] && d[v] > d[u] + cost) {
d[v] = d[u] + cost;
q.push(node(v, d[v]));
}
}
}
}
inline int A_star(int st, int ed) {
priority_queue<node> q;
q.push(node(st, 0));
--k;
while (!q.empty()) {
node tmp = q.top();
q.pop();
int u = tmp.v;
if (u == ed) {
if (k)
--k;
else
return tmp.cost;
}
int len = revE[u].size();
for (int i = 0; i < len; ++i) {
int v = revE[u][i].v;
int cost = revE[u][i].cost;
q.push(node(v, tmp.cost + cost));
}
}
return -1;
}
inline void addedge(int u, int v, int w) {
revE[u].push_back(Edge(v, w));
E[v].push_back(Edge(u, w));
}
int st, ed;
inline void RUN() {
while (~scanf("%d %d", &n, &m)) {
for (int i = 0; i <= n; ++i) {
E[i].clear();
revE[i].clear();
}
scanf("%d %d %d %lld", &st, &ed, &k, &T);
for (int i = 1; i <= m; ++i) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
addedge(u, v, w);
}
Dijstra(ed);
if (d[st] == INF) {
puts("Whitesnake!");
continue;
}
int ans = A_star(st, ed);
if (ans == -1) {
puts("Whitesnake!");
continue;
}
puts(ans <= T ? "yareyaredawa" : "Whitesnake!");
}
}
int main() {
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
RUN();
#ifdef LOCAL_JUDGE
fclose(stdin);
#endif // LOCAL_JUDGE
}
E. The cake is a lie
留坑。
F. Fantastic Graph
题意:
给出一张二分图,若干条边,选择一些边进去,使得所有点的度数在
思路:
XDL 说爆搜,加上优秀的剪枝(8ms)。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int maxn = 1e4 + 10;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
struct node {
int l, r;
inline node() {}
inline node(int l, int r) : l(l), r(r) {}
} arr[maxn];
bool flag = false;
int n, m, k;
int sum;
int res_L;
int res_R;
int L, R;
int du_left[maxn];
int du_right[maxn];
inline void Init() {
memset(du_left, 0, sizeof du_left);
memset(du_right, 0, sizeof du_right);
}
inline void DFS(int idx, int cnt) {
if (sum == n + m) {
flag = true;
return;
}
if (idx > k)
return;
if (k - idx + 1 + cnt < res_L)
return;
if (cnt >= res_R)
return;
if (flag)
return;
// do
if (du_left[arr[idx].l] < R && du_right[arr[idx].r] < R) {
du_left[arr[idx].l]++;
du_right[arr[idx].r]++;
if (du_left[arr[idx].l] == L)
sum++;
if (du_right[arr[idx].r] == L)
sum++;
DFS(idx + 1, cnt + 1);
if (flag)
return;
if (du_left[arr[idx].l] == L)
sum--;
if (du_right[arr[idx].r] == L)
sum--;
du_left[arr[idx].l]--;
du_right[arr[idx].r]--;
}
// not do
DFS(idx + 1, cnt);
if (flag)
return;
}
inline void RUN() {
int cas = 0;
while (~scanf("%d %d %d", &n, &m, &k)) {
printf("Case %d: ", ++cas);
Init();
scanf("%d %d", &L, &R);
int cnt = 0;
for (int i = 1; i <= k; ++i) {
scanf("%d %d", &arr[i].l, &arr[i].r);
du_left[arr[i].l]++;
du_right[arr[i].r]++;
if (du_left[arr[i].l] == L)
cnt++;
if (du_right[arr[i].r] == L)
cnt++;
}
if (L == 0) {
puts("Yes");
continue;
}
if (cnt != n + m) {
puts("No");
continue;
}
sum = 0;
res_L = ((n + m) * L + 1) / 2;
res_R = ((n + m) * R) / 2;
Init();
flag = false;
DFS(1, 0);
puts(flag ? "Yes" : "No");
}
}
int main() {
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
RUN();
#ifdef LOCAL_JUDGE
fclose(stdin);
#endif // LOCAL_JUDGE
}
G. Spare Tire
题意:
给定一个数列
思路:
首先可以发现:
因为
考虑到:
所以
所以我们可以用容斥。在前
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int maxn = 1e4 + 10;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
int tot;
bool isprime[maxn];
int prime[maxn];
ll inv[maxn];
inline void Init_prime() {
inv[1] = 1;
for (int i = 2; i < maxn; ++i) {
inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
}
memset(isprime, true, sizeof isprime);
tot = 0;
for (int i = 2; i < maxn; ++i) {
if (isprime[i]) {
prime[tot++] = i;
for (int j = (i << 1); j < maxn; j += i) {
isprime[i] = false;
}
}
}
}
vector<ll> vec;
ll n, m;
ll ans;
inline void Init(ll x) {
vec.clear();
for (int i = 0; i < tot && prime[i] < x; ++i) {
if (x % prime[i] == 0) {
vec.push_back(prime[i]);
while (x % prime[i] == 0) {
x /= prime[i];
}
}
}
if (x != 1)
vec.push_back(x);
}
inline void RUN() {
Init_prime();
while (~scanf("%lld %lld", &n, &m)) {
ans = n % MOD * (n + 1) % MOD * (n + 2) % MOD * inv[3] % MOD;
if (m == 1) {
printf("%lld\n", ans);
continue;
}
Init(m);
int len = vec.size();
for (int i = 1; i < (1 << len); ++i) {
int cnt = 0;
ll t = 1;
for (int j = 0; j < len; ++j) {
if (i & (1 << j)) {
cnt++;
t *= vec[j];
}
}
ll x = n / t;
ll tmp = x % MOD * (x + 1) % MOD * (2 * x % MOD + 1) % MOD * inv[6] % MOD * t % MOD * (t + 1) % MOD -
x % MOD * (x + 1) % MOD * (x - 1) % MOD * inv[3] % MOD * t % MOD;
tmp = (tmp + MOD) % MOD;
if (cnt & 1) {
ans = (ans - tmp + MOD) % MOD;
} else {
ans = (ans + tmp) % MOD;
}
}
printf("%lld\n", ans);
}
}
int main() {
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
RUN();
#ifdef LOCAL_JUDGE
fclose(stdin);
#endif // LOCAL_JUDGE
}
H. Hamming Weight
留坑。
I. Lattice's basics in digital electronics
按题意模拟即可。
Code
#include <bits/stdc++.h>
using namespace std;
#define N 100010
int t, n, m;
string str, tmp, ttmp, ans, s;
unordered_map<string, char> mp;
unordered_map<char, string> mmp;
inline void Init() {
mmp.clear();
mmp['0'] = "0000";
mmp['1'] = "0001";
mmp['2'] = "0010";
mmp['3'] = "0011";
mmp['4'] = "0100";
mmp['5'] = "0101";
mmp['6'] = "0110";
mmp['7'] = "0111";
mmp['8'] = "1000";
mmp['9'] = "1001";
mmp['A'] = "1010";
mmp['B'] = "1011";
mmp['C'] = "1100";
mmp['D'] = "1101";
mmp['E'] = "1110";
mmp['F'] = "1111";
mmp['a'] = "1010";
mmp['b'] = "1011";
mmp['c'] = "1100";
mmp['d'] = "1101";
mmp['e'] = "1110";
mmp['f'] = "1111";
}
inline bool ok(string s) {
int cnt = 0;
for (int i = 0; i < 8; ++i) cnt += (s[i] == '1');
if ((s[8] == '0' && (cnt & 1)) || (s[8] == '1' && (cnt & 1) == 0))
return true;
return false;
}
inline void Run() {
cin.tie(0), cout.tie(0);
Init();
ios::sync_with_stdio(false);
cin >> t;
while (t--) {
mp.clear();
cin >> m >> n;
for (int i = 1, num; i <= n; ++i) {
cin >> num >> str;
mp[str] = num;
}
cin >> s;
tmp = "";
str = "";
for (int i = 0, len = s.size(); i < len; ++i) tmp += mmp[s[i]];
for (int i = 0, len = tmp.size(); i < len;) {
if (len - i < 9)
break;
ttmp = "";
for (int cnt = 0; cnt < 9; ++cnt, ++i) ttmp += tmp[i];
if (ok(ttmp)) {
ttmp.erase(ttmp.end() - 1);
str += ttmp;
// cout << ttmp << endl;
}
}
// for (auto it : mp) cout << it.first << " " << it.second << endl;
ans.clear(), tmp.clear();
for (int i = 0, len = str.size(); i < len && ans.size() < m; ++i) {
tmp += str[i];
if (mp.find(tmp) != mp.end()) {
ans += mp[tmp];
tmp = "";
}
}
cout << ans << endl;
}
}
int main() {
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif
Run();
return 0;
}
J. Ka Chang
题意:
两种操作:
所有深度为 的加上 。 查询以 为根的所有子节点的和。
思路:
以
然后对于更新操作,考虑两种方法操作:
- 暴力更新每个点
- 记录这个深度更新了多少,查询的时候找出这个深度中有子节点有几个,直接加上。
如果只用第二个操作更新,那么当给的树是一条链的时候,查询的复杂度达到
只用第一个操作更新,那么更新的操作当给的树是菊花形的时候,更新的复杂度达到
那么考虑将两种操作结合,当某个深度中元素个数大于
然后查询的时候,要记得都加上。
Code
#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define ll long long
struct Edge {
int to, nx;
inline Edge() {}
inline Edge(int to, int nx) : to(to), nx(nx) {}
} edge[N << 1];
int n, q, Maxdeep;
int head[N], pos;
int ord[N], son[N], deep[N], fa[N], cnt;
vector<int> dep[N], Lar;
ll sum[N];
inline void Init() {
memset(head, -1, sizeof head);
pos = 0;
cnt = 0;
Maxdeep = 0;
Lar.clear();
for (int i = 0; i <= 1; ++i) dep[i].clear();
fa[1] = 1;
deep[1] = 0;
}
inline void addedge(int u, int v) {
edge[++pos] = Edge(v, head[u]);
head[u] = pos;
}
inline void DFS(int u, int pre) {
ord[u] = ++cnt;
dep[deep[u]].emplace_back(cnt);
Maxdeep = max(Maxdeep, deep[u]);
for (int it = head[u]; ~it; it = edge[it].nx) {
int v = edge[it].to;
if (v == pre)
continue;
deep[v] = deep[u] + 1;
DFS(v, u);
}
son[u] = cnt;
}
struct node {
int l, r;
ll sum;
inline node() {}
inline node(int l, int r, ll sum) : l(l), r(r), sum(sum) {}
} tree[N << 2];
inline void pushup(int id) {
tree[id].sum = tree[id << 1].sum + tree[id << 1 | 1].sum;
}
inline void build(int id, int l, int r) {
tree[id] = node(l, r, 0);
if (l == r)
return;
int mid = (l + r) >> 1;
build(id << 1, l, mid);
build(id << 1 | 1, mid + 1, r);
}
inline void update(int id, int pos, ll val) {
if (tree[id].l == tree[id].r) {
tree[id].sum += val;
return;
}
int mid = (tree[id].l + tree[id].r) >> 1;
if (pos <= mid)
update(id << 1, pos, val);
else if (pos > mid)
update(id << 1 | 1, pos, val);
pushup(id);
}
ll anssum;
inline void query(int id, int l, int r) {
if (tree[id].l >= l && tree[id].r <= r) {
anssum += tree[id].sum;
return;
}
int mid = (tree[id].l + tree[id].r) >> 1;
if (l <= mid)
query(id << 1, l, r);
if (r > mid)
query(id << 1 | 1, l, r);
}
inline void Run() {
while (scanf("%d%d", &n, &q) != EOF) {
Init();
for (int i = 1, u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
DFS(1, 1);
build(1, 1, n);
int limit = (int)sqrt(100000);
for (int i = 1; i <= Maxdeep; ++i) {
if (dep[i].size() >= limit) {
Lar.emplace_back(i);
sort(dep[i].begin(), dep[i].end());
}
}
for (int i = 1, op, l, x; i <= q; ++i) {
scanf("%d", &op);
if (op == 1) {
scanf("%d%d", &l, &x);
if (dep[l].size() < limit) {
for (auto it : dep[l]) update(1, it, (ll)x);
} else
sum[l] += (ll)x;
} else {
scanf("%d", &x);
anssum = 0;
query(1, ord[x], son[x]);
ll ans = anssum;
int l = ord[x], r = son[x];
for (auto it : Lar) {
if (it < deep[x])
continue;
int k = upper_bound(dep[it].begin(), dep[it].end(), r) -
lower_bound(dep[it].begin(), dep[it].end(), l);
if (k == 0)
break;
ans += sum[it] * k;
}
printf("%lld\n", ans);
}
}
}
}
int main() {
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif
Run();
return 0;
}
K. Supreme Number
只有几个数,爆搜出来,判断一下
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int maxn = 2e6 + 10;
string s[] = {"1", "2", "3", "5", "7", "11", "13", "17", "23", "31", "37", "53", "71", "73", "113", "131", "137", "173",
"311", "317"};
inline void RUN() {
int t;
cin >> t;
for (int cas = 1; cas <= t; ++cas) {
cout << "Case #" << cas << ": ";
string ans;
string str;
cin >> str;
for (int i = 0; i < 20; ++i) {
if (str.length() == s[i].length()) {
if (str >= s[i])
ans = s[i];
} else if (str.length() < s[i].length()) {
continue;
} else
ans = s[i];
}
cout << ans << endl;
}
}
int main() {
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
RUN();
#ifdef LOCAL_JUDGE
fclose(stdin);
#endif // LOCAL_JUDGE
}
Last update: March 31, 2022
Created: March 31, 2022
Created: March 31, 2022