code:
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int maxn = 1e3 + 9;
int n;
int a[maxn], cnt;
struct tree
{
int val, ls, rs;
}tr[maxn << 2];
int path[maxn];
inline void add(int x, int rt)
{
if(tr[x].val < tr[rt].val)
{
if(tr[rt].ls) add(x, tr[rt].ls);
else tr[rt].ls = x;
}
else
{
if(tr[rt].rs) add(x, tr[rt].rs);
else tr[rt].rs = x;
}
}
void dfs1(int rt)// 前序
{
path[++cnt] = tr[rt].val;
if(tr[rt].ls) dfs1(tr[rt].ls);
if(tr[rt].rs) dfs1(tr[rt].rs);
}
void dfs2(int rt)// 后续
{
if(tr[rt].ls) dfs2(tr[rt].ls);
if(tr[rt].rs) dfs2(tr[rt].rs);
path[++cnt] = tr[rt].val;
}
void dfs3(int rt)// 镜像前序
{
path[++cnt] = tr[rt].val;
if(tr[rt].rs) dfs3(tr[rt].rs);
if(tr[rt].ls) dfs3(tr[rt].ls);
}
void dfs4(int rt)// 镜像后序
{
if(tr[rt].rs) dfs4(tr[rt].rs);
if(tr[rt].ls) dfs4(tr[rt].ls);
path[++cnt] = tr[rt].val;
}
void work()
{
cin >> n;
for(int i = 1; i <= n; ++i) cin >> tr[i].val;
for(int i = 2; i <= n; ++i) add(i, 1);
bool f = 1;
dfs1(1);
for(int i = 1; i <= cnt; ++i) if(path[i] != tr[i].val)
{
f = 0; break;
}
if(f)
{
cnt = 0;
dfs2(1);
cout << "YES\n";
for(int i = 1; i <= n; ++i)
cout << path[i] << " \n"[i==n];
return;
}
cnt = 0;f = 1;
dfs3(1);
for(int i = 1; i <= n; ++i) if(path[i] != tr[i].val)
{
f = 0; break;
}
if(f)
{
cnt = 0;
dfs4(1);
cout << "YES\n";
for(int i = 1; i <= n; ++i)
cout << path[i] << " \n"[i==n];
return;
}
cout << "NO" << endl;
}
int main()
{
ios::sync_with_stdio(0);
work();
return 0;
}
L2-006 树的遍历 (25 分)
根据后序遍历与中序遍历建二叉树
可以学一下手动还原
代码就是模拟的这种还原方式
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ls (p << 1)
#define rs (p << 1 | 1)
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 1e9 + 7;
ll n, m;
int last[maxn], mid[maxn], ans[maxn];
void build(int l, int r, int rt, int p)
{
if(l > r) return;
int pos = l;
while(pos <= r && mid[pos] != last[rt]) ++pos;
ans[p] = last[rt];
build(l, pos - 1, rt - 1 - (r - pos), ls);
build(pos + 1, r, rt - 1, rs);
}
void work()
{
memset(ans, -1, sizeof(ans));
cin >> n;
for(int i = 1; i <= n; ++i) cin >> last[i];
for(int i = 1; i <= n; ++i) cin >> mid[i];
build(1, n, n, 1);
vector <int> v;
for(int i = 1; i < maxn; ++i) if(ans[i] != -1)
v.push_back(ans[i]);
for(int i = 0; i < (int)v.size() - 1; ++i) cout << v[i] << " ";
cout << v.back() << endl;
}
int main()
{
ios::sync_with_stdio(0);
//int TT;cin>>TT;while(TT--)
work();
return 0;
}
L2-014 列车调度 (25 分)
裸的最长上升子序列(如果你知道Dilworth定理
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define eps 1e-3
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 1e9 + 7;
ll n, m;
void work()
{
int n;
cin >> n;
set <int> se;
for(int i = 1; i <= n; ++i)
{
int x;cin >> x;
auto it = se.lower_bound(x);
if(it != se.end())
{
se.erase(*it);
se.insert(x);
}
else se.insert(x);
}
cout << se.size();
}
int main()
{
ios::sync_with_stdio(0);
//int TT;cin>>TT;while(TT--)
work();
return 0;
}
L2-013 红色警报 (25 分)
这个题和这个第四题差不多
离线查询,倒着遍历查询
并查集维护连通块
如果加入一个点,这个点连接了至少两个连通块,那么就是发出红色警报的
我们用
s
e
t
set
set 维护一下这个点连接的所有可连接点的
f
a
t
h
e
r
father
father 即可判断连通块个数
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int maxn = 1e3 + 9;
const int mod = 1e9 + 7;
int n, m;
int f[maxn];
int pos[maxn];
vector <int> e[maxn];
int Find(int x)
{
return x == f[x] ? x : f[x] = Find(f[x]);
}
void work()
{
cin >> n >> m;
for(int i = 0; i < n; ++i) f[i] = i;
for(int i = 1; i <= m; ++i)
{
int x, y;cin >> x >> y;
e[x].push_back(y);e[y].push_back(x);
}
int k;cin >> k;
vector <int> q;
for(int i = 1; i <= k; ++i)
{
int x;cin >> x;
q.push_back(x);
pos[x] = 1;
}
for(int i = 0; i < n; ++i) if(!pos[i])
{
for(int j = 0; j < e[i].size(); ++j) if(!pos[e[i][j]])
{
int x = Find(i), y = Find(e[i][j]);
if(x != y) f[x] = y;
}
}
stack <string> s;
for(int i = k - 1; i >= 0; --i)// 先把没有被占领的节点连接处理一下
{
pos[q[i]] = 0;
set<int> se;
for(int j = 0; j < e[q[i]].size(); ++j) if(!pos[e[q[i]][j]])
{
int x = Find(q[i]), y = Find(e[q[i]][j]);
if(x != y){
f[y] = x;
se.insert(y);
}
}
if(se.size() > 1) {
string s1 = "Red Alert: City ";
string s2 = " is lost!";
string s3 = to_string(q[i]);
s.push(s1 + s3 + s2);
}
else {
string s1 = "City ";
string s2 = " is lost.";
string s3 = to_string(q[i]);
s.push(s1 + s3 + s2);
}
}
while(!s.empty())
{
cout << s.top();
s.pop();
if(s.size() || k == n) cout << endl;
}
if(k == n) cout << "Game Over.";
}
int main()
{
ios::sync_with_stdio(0);
//int TT;cin>>TT;while(TT--)
work();
return 0;
}
L2-023 图着色问题 (25 分)
坑点是这 K 个颜色必须全部用上,否则不算一个解
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define eps 1e-3
using namespace std;
const int maxn = 1e6 + 9;
const int mod = 1e9 + 7;
ll n, m;
int V, E, K;
struct Edge
{
int to, next;
}e[maxn];
int head[maxn], cnt, vis[maxn], color[maxn];
inline void add(int x, int y)
{
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
bool check()
{
for(int i = 1; i <= V; ++i)
{
for(int j = head[i]; j; j = e[j].next)
{
int to = e[j].to;
//cout << i << " " << color[i] << " " << to << " " << color[to] << endl;
if(color[i] == color[to]) return false;
}
}
return true;
}
void work()
{
cin >> V >> E >> K;
for(int i = 1; i <= E; ++i)
{
int x, y;cin >> x >> y;
add(x, y);add(y, x);
}
int k;cin >> k;
for(int i = 1; i <= k; ++i)
{
set<int> se;
for(int j = 1; j <= V; ++j)
cin >> color[j], se.insert(color[j]);
if(se.size() == K && check()) cout << "Yes\n";
else cout << "No\n";
}
}
int main()
{
ios::sync_with_stdio(0);
//int TT;cin>>TT;while(TT--)
//while(cin >> n)
work();
return 0;
}
L2-001 紧急救援 (25 分)
和里面的英文版 Emergency 几乎一样
用个 pre 记录下路径就完事了
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int maxn = 1e6 + 9;
const int mod = 1000000009;
const int inf = 0x3f3f3f3f;
int n, m;
struct node
{
int to, next, w;
}e[maxn * 2];
int head[maxn], cnt;
int pre[maxn];
inline void add(int x, int y, int z)
{
e[++cnt].to = y;
e[cnt].next = head[x];
e[cnt].w = z;
head[x] = cnt;
}
int dis[maxn], ans[maxn], W[maxn], res[maxn];
bool vis[maxn];
priority_queue <pair<int,int>, vector<pair<int,int> >, greater<pair<int,int> > > q;
void work()
{
int c1, c2;
cin >> n >> m >> c1 >> c2;
int u, v, w;
for(int i = 0; i < n; ++i) cin >> W[i];
for(int i = 1; i <= m; ++i)
{
cin >> u >> v >> w;add(u, v, w);add(v, u, w);
}
for(int i = 0; i < n; ++i)
dis[i] = 1e9, vis[i] = 0;
dis[c1] = 0, ans[c1] = 1;
q.push({0, c1});
res[c1] = W[c1];// 初始化起点价值
while(!q.empty())
{
int now = q.top().second;q.pop();
if(vis[now]) continue;
vis[now] = 1;
for(int i = head[now]; i; i = e[i].next)
{
int tmp = e[i].to;
if(dis[tmp] > dis[now] + e[i].w)
{
dis[tmp] = dis[now] + e[i].w;
ans[tmp] = ans[now];
res[tmp] = res[now] + W[tmp];
pre[tmp] = now;
q.push({dis[tmp], tmp});
}
else if(dis[tmp] == dis[now] + e[i].w)
{
ans[tmp] += ans[now];
if(res[tmp] < res[now] + W[tmp]) pre[tmp] = now;
res[tmp] = max(res[tmp], res[now] + W[tmp]);
}
}
}
cout << ans[c2] << " " << res[c2] << endl;
stack <int> st;
int j = c2;
while(j != c1)
{
st.push(j);
j = pre[j];
}
st.push(c1);
while(!st.empty())
{
cout << st.top();
st.pop();
if(st.size()) cout << " ";
else cout << endl;
}
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
//int TT;cin>>TT;while(TT--)
work();
return 0;
}
1010 Radix (25 分)
题意:
给定两个不超过
9
9
9 为的数,一个
t
a
g
tag
tag 表示 后边的进制
b
a
s
e
base
base 是第一个数还是第二个数,对于不知道进制的数,找到一个合理的进制,使得两个数相等
思路:
这个题保证了给进制的数转化成
10
10
10 进制不会爆
l
l
ll
ll(虽然它没说
二分答案,当前进制为
m
i
d
mid
mid,转成
10
10
10 进制如果爆
l
l
ll
ll 或者 大于
n
u
m
num
num_
a
a
a,则说明
m
i
d
mid
mid 偏大
ps:感觉这个题好难写
code:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
using namespace std;
const int maxn = 1e5 + 9;
const int mod = 1e9 + 7;
unordered_map<char, int> ma;
ll n, m;
ll to_num(string s, ll base)
{
ll ans = 0;
for(int i = 0; i < s.size(); ++i)
ans = ans * base + ma[s[i]];
return ans;
}
void work()
{
for(int i = 0; i < 36; ++i)
{
char tmp = i < 10 ? i + '0' : i - 10 + 'a';
ma[tmp] = i;
}
string a, b;
ll k, num;
cin >> a >> b >> k >> num;
if(k == 2) swap(a, b);
ll num_a = to_num(a, num);
ll l = -1, r = num_a;
for(auto x : b) l = max(l, 1ll * (ma[x] + 1));
while(l < r)
{
ll mid = (l + r) >> 1;
ll t = to_num(b, mid);
if(t < 0 || t >= num_a) r = mid;
else l = mid + 1;
}
if(to_num(b, l) != num_a) l = -1;
if(l == -1) cout << "Impossible\n";
else cout << l << endl;
}
int main()
{
ios::sync_with_stdio(0);
//int TT;cin>>TT;while(TT--)
work();
return 0;
}
1515

被折叠的 条评论
为什么被折叠?



