ACM-ICPC 2018 沈阳赛区网络预赛 Solution
A. Gudako and Ritsuka
留坑。
B. Call of Accepted
题意:定义了一种新的运算符$x d y$ 然后给出中缀表达式,求值
思路:先中缀转后缀,然后考虑如何最大如何最小,按题意模拟即可
#include <bits/stdc++.h>
using namespace std; #define ll long long char s[];
ll suffix[];
int vis[]; unordered_map <char, int> mp; inline void Init()
{
mp.clear();
mp['('] = ;
mp['+'] = ;
mp['-'] = ;
mp['*'] = ;
mp['d'] = ;
} 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, , sizeof vis);
int cnt = ;
for (int i = , len = strlen(s); i < len; ++i)
{
if (isdigit(s[i]))
{
ll tmp = ; int flag = ;
if (i == && s[] == '-') symbol.pop(), flag = -;
else if (i > && s[i - ] == '-' && s[i - ] == '(') symbol.pop(), flag = -;
for (; i < len && isdigit(s[i]); ++i)
{
tmp = tmp * + s[i] - '';
}
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 ()
{
int top = symbol.top(); symbol.pop();
if (top == '(') break;
suffix[++cnt] = top;
vis[cnt] = ;
}
}
else
{
while (!symbol.empty() && mp[symbol.top()] >= mp[s[i]])
{
suffix[++cnt] = symbol.top(); symbol.pop();
vis[cnt] = ;
}
symbol.emplace(s[i]);
}
}
}
while (!symbol.empty())
{
suffix[++cnt] = symbol.top(); symbol.pop();
vis[cnt] = ;
}
for (int i = ; 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 ;
}
C. Convex Hull
留坑。
D. Made In Heaven
题意:找第k短路
思路:A_star
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1e9 + ;
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 = ; i <= n; ++i)
{
d[i] = INF;
}
priority_queue<node>q;
d[st] = ;
q.push(node(st, ));
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 = ; 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, ));
--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 = ; i < len; ++i)
{
int v = revE[u][i].v;
int cost = revE[u][i].cost;
q.push(node(v, tmp.cost + cost));
}
}
return -;
} 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 = ; i <= n; ++i)
{
E[i].clear();
revE[i].clear();
}
scanf("%d %d %d %lld", &st, &ed, &k, &T);
for (int i = ; 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 == -)
{
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
题意:给出一张二分图,若干条边,选择一些边进去,使得所有点的度数在$[L,R]$ 之间
思路:XDL说爆搜,加上优秀的剪枝(8ms)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
const int maxn = 1e4 + ;
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, , sizeof du_left);
memset(du_right, , sizeof du_right);
} inline void DFS(int idx, int cnt)
{
if (sum == n + m)
{
flag = true;
return;
}
if (idx > k) return;
if (k - idx + + 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 + , cnt + );
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 + , cnt);
if (flag) return;
} inline void RUN()
{
int cas = ;
while (~scanf("%d %d %d", &n, &m, &k))
{
printf("Case %d: ", ++cas);
Init();
scanf("%d %d", &L, &R);
int cnt = ;
for (int i = ; 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 == )
{
puts("Yes");
continue;
}
if (cnt != n + m )
{
puts("No");
continue;
}
sum = ;
res_L = ((n + m) * L + ) / ;
res_R = ((n + m) * R) / ;
Init();
flag = false;
DFS(, );
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
题意:给定一个数列A,两个整数n,m,在1-n中所有与m互质的数记为$b[i]$,求$\sum_{i = 1}^{i = p} a_{b_i}$
思路:首先可以发现$A[i]=i*(i+1)=i^2+i$。A的前n项和为$\frac{n*(n+1)*(2n+1)}{6}+\frac{n*(n+1)}{2}$
因为n,m很大有1e8,而且一共有15000个case,所以筛法肯定不行。
考虑到2*3*5*7*11*13*17*19*23=223092870>1e8,所以m的质因子的种类肯定少于9个。
所以我们可以用容斥。在前n项的和的基础上容斥包含m的不同因子的项。时间复杂度最多为$2^9$。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
const int maxn = 1e4 + ;
const ll INFLL = 0x3f3f3f3f3f3f3f3f; int tot;
bool isprime[maxn];
int prime[maxn];
ll inv[maxn]; inline void Init_prime()
{
inv[] = ;
for (int i = ; i < maxn; ++i)
{
inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
}
memset(isprime, true, sizeof isprime);
tot = ;
for (int i = ; i < maxn; ++i)
{
if (isprime[i])
{
prime[tot++] = i;
for (int j = (i << ); 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 = ; i < tot && prime[i] < x; ++i)
{
if (x % prime[i] == )
{
vec.push_back(prime[i]);
while (x % prime[i] == )
{
x /= prime[i];
}
}
}
if (x != ) vec.push_back(x);
} inline void RUN()
{
Init_prime();
while (~scanf("%lld %lld", &n, &m))
{
ans = n % MOD * (n + ) % MOD * (n + ) % MOD * inv[] % MOD;
if (m == )
{
printf("%lld\n", ans);
continue;
}
Init(m);
int len = vec.size();
for (int i = ; i < ( << len); ++i)
{
int cnt = ;
ll t = ;
for (int j = ; j < len; ++j)
{
if (i & ( << j))
{
cnt++;
t *= vec[j];
}
}
ll x = n / t;
ll tmp = x % MOD * (x + ) % MOD * ( * x % MOD + ) % MOD * inv[] % MOD * t % MOD * (t + ) % MOD - x % MOD * (x + ) % MOD * (x - ) % MOD * inv[] % MOD * t % MOD;
tmp = (tmp + MOD) % MOD;
if (cnt & )
{
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
按题意模拟即可。
#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[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp[''] = "";
mmp['A'] = "";
mmp['B'] = "";
mmp['C'] = "";
mmp['D'] = "";
mmp['E'] = "";
mmp['F'] = "";
mmp['a'] = "";
mmp['b'] = "";
mmp['c'] = "";
mmp['d'] = "";
mmp['e'] = "";
mmp['f'] = "";
} inline bool ok(string s)
{
int cnt = ;
for (int i = ; i < ; ++i) cnt += (s[i] == '');
if ((s[] == '' && (cnt & )) || (s[] == '' && (cnt & ) == )) return true;
return false;
} inline void Run()
{
cin.tie(), cout.tie(); Init();
ios::sync_with_stdio(false);
cin >> t;
while (t--)
{
mp.clear(); cin >> m >> n;
for (int i = , num; i <= n; ++i)
{
cin >> num >> str;
mp[str] = num;
}
cin >> s; tmp = ""; str = "";
for (int i = , len = s.size(); i < len; ++i)
tmp += mmp[s[i]];
for (int i = , len = tmp.size(); i < len; )
{
if (len - i < ) break;
ttmp = "";
for (int cnt = ; cnt < ; ++cnt, ++i)
ttmp += tmp[i];
if (ok(ttmp))
{
ttmp.erase(ttmp.end() - );
str += ttmp;
//cout << ttmp << endl;
}
}
//for (auto it : mp) cout << it.first << " " << it.second << endl;
ans.clear(), tmp.clear();
for (int i = , 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 ;
}
J. Ka Chang
题意:两种操作 $1 L X$ 所有深度为L的加上x $2 X$ 查询以x为根的所有子节点的和
思路:以x为根的子节点的和可以用DFS序使得所有子树的标号在一块
然后对于更新操作,考虑两种方法操作
1° 暴力更新每个点
2° 记录这个深度更新了多少,查询的时候找出这个深度中有子节点有几个 直接加上
如果只用第二个操作更新,那么当给的树是一条链的时候,查询的复杂度达到$O(nlogn)$
只用第一个操作更新,那么更新的操作当给的树是菊花形的时候,更新的复杂度达到$O(nlogn)$
那么考虑将两种操作结合,当某个深度中元素个数大于sqrt(100000) 的时候,用第二种操作 否则用第一种
然后查询的时候 要记得 都加上
#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 << ]; 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, -, sizeof head);
pos = ; cnt = ; Maxdeep = ; Lar.clear();
for (int i = ; i <= ; ++i) dep[i].clear();
fa[] = ; deep[] = ;
} 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] + ;
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 << ]; inline void pushup(int id)
{
tree[id].sum = tree[id << ].sum + tree[id << | ].sum;
} inline void build(int id, int l, int r)
{
tree[id] = node(l, r, );
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , 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) >> ;
if (pos <= mid) update(id << , pos, val);
else if (pos > mid) update(id << | , 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) >> ;
if (l <= mid) query(id << , l, r);
if (r > mid) query(id << | , l, r);
} inline void Run()
{
while (scanf("%d%d", &n, &q) != EOF)
{
Init();
for (int i = , u, v; i < n; ++i)
{
scanf("%d%d", &u, &v);
addedge(u, v); addedge(v, u);
}
DFS(, ); build(, , n);
int limit = (int)sqrt();
for (int i = ; i <= Maxdeep; ++i)
{
if (dep[i].size() >= limit)
{
Lar.emplace_back(i);
sort(dep[i].begin(), dep[i].end());
}
}
for (int i = , op, l, x; i <= q; ++i)
{
scanf("%d", &op);
if (op == )
{
scanf("%d%d", &l, &x);
if (dep[l].size() < limit)
{
for (auto it : dep[l]) update(, it, (ll)x);
}
else
sum[l] += (ll)x;
}
else
{
scanf("%d", &x);
anssum = ; query(, 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 == ) break;
ans += sum[it] * k;
}
printf("%lld\n", ans);
}
}
}
} int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run();
return ;
}
K. Supreme Number
只有几个数,爆搜出来,判断一下
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1e9 + ;
const int INF = 0x3f3f3f3f;
const int maxn = 2e6 + ; string s[] = { "","","","","","","","","","","","","","","","","","","","" }; inline void RUN()
{
int t;
cin >> t;
for (int cas = ; cas <= t; ++cas)
{
cout << "Case #" << cas << ": ";
string ans;
string str;
cin >> str;
for (int i = ; i < ; ++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();
cout.tie();
RUN(); #ifdef LOCAL_JUDGE
fclose(stdin);
#endif // LOCAL_JUDGE }
ACM-ICPC 2018 沈阳赛区网络预赛 Solution的更多相关文章
- ACM-ICPC 2018 沈阳赛区网络预赛 K Supreme Number(规律)
https://nanti.jisuanke.com/t/31452 题意 给出一个n (2 ≤ N ≤ 10100 ),找到最接近且小于n的一个数,这个数需要满足每位上的数字构成的集合的每个非空子集 ...
- ACM-ICPC 2018 沈阳赛区网络预赛-K:Supreme Number
Supreme Number A prime number (or a prime) is a natural number greater than 11 that cannot be formed ...
- ACM-ICPC 2018 沈阳赛区网络预赛-D:Made In Heaven(K短路+A*模板)
Made In Heaven One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with her. ...
- 图上两点之间的第k最短路径的长度 ACM-ICPC 2018 沈阳赛区网络预赛 D. Made In Heaven
131072K One day in the jail, F·F invites Jolyne Kujo (JOJO in brief) to play tennis with her. Howe ...
- ACM-ICPC 2018 沈阳赛区网络预赛 J树分块
J. Ka Chang Given a rooted tree ( the root is node 11 ) of NN nodes. Initially, each node has zero p ...
- ACM-ICPC 2018 沈阳赛区网络预赛 K. Supreme Number
A prime number (or a prime) is a natural number greater than 11 that cannot be formed by multiplying ...
- ACM-ICPC 2018 沈阳赛区网络预赛 F. Fantastic Graph
"Oh, There is a bipartite graph.""Make it Fantastic." X wants to check whether a ...
- Fantastic Graph 2018 沈阳赛区网络预赛 F题
题意: 二分图 有k条边,我们去选择其中的几条 每选中一条那么此条边的u 和 v的度数就+1,最后使得所有点的度数都在[l, r]这个区间内 , 这就相当于 边流入1,流出1,最后使流量平衡 解析: ...
- 【ACM-ICPC 2018 沈阳赛区网络预赛】不太敢自称官方的出题人题解
A. Gudako and Ritsuka 链接 by Yuki & Asm.Def 期望难度:Hard- 考虑从后往前进行博弈动态规划,在这一过程中维护所有的先手必胜区间.区间不妨采用左开右 ...
随机推荐
- ref 属性使用eslint报错
react 使用 ref 报错 ,[eslint] Using string literals in ref attributes is deprecated. (react/no-string-re ...
- 苹果降频门:旧款iPhone哪些功能受到影响
要说苹果最近发生的大事,就数网络上传的沸沸扬扬的降频门事件了,近期苹果在新发布的iOS 11系统中新增了一项功能,意在降低旧款手机的电量消耗,但限制了旧款iPhone的性能,那么iPhone有哪些功能 ...
- linux文件锁flock【转】
转自: https://www.cnblogs.com/kex1n/p/7100107.html linux文件锁flock 在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要 ...
- saltstack远程执行命令.md
saltstack 支持在master上向client 远程执行命令,并显示命令执行的结果 命令格式: salt '<操作目标>' <方法> [参数] 示例 示例1 ping检 ...
- poj_2553 强连通分支&出度为0的点
题目大意 N个点的有向图中,定义“好点”为: 从该点v出发可以到达的所有点u,均有一条路径使得u可达v. 求出图中所有的“好点”,并按照顺序从小到大输出出来. 题目分析 图存在多个强连通分支,强连通分 ...
- 【linux】Crontab 定时任务 使用实例
1 使用putty 登录linux 服务器 2 输入以下命令.查看已有的定时任务 crontab -l 3 输入 以下命令,进入定时任务文件 crontab -e 4 键盘 选择 i 键 进行输 ...
- Django 1.5.4 专题二 urls 和 view 提高
一.修改article/urls.py内容如下 二.修改django_test/urls.py如下 三.修改article/views.py如下 四.修改templates/article.html的 ...
- Unity3D 笔记二 3D模型基础
一.3D模型基础 1.Hierarchy 显示的是界面上的游戏对象(GameObject),每个游戏对象都有.至少要有一个Camera,点击Camera就可以在Preview中看到摄像机的视角画面.每 ...
- Linux系统下JDK安装配置(转载)
转载出处:http://www.cnblogs.com/xuliangxing/p/7066913.html 本文主要介绍的是如何是Linux环境下安装JDK的,因为Linux环境下,很多时候也离不开 ...
- 【git】------git的基本命令------【巷子】
001.初始化仓库,创建git仓库 git init 002.配置个人信息 git config --global user.name <名字> --------->:配置用户名 g ...