题目链接
用优先队列模拟一下,需要注意要用map存储一下每个数字出现的次数进行优化,否则会t
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
void solve()
{
int n;
cin >> n;
int ans = 0;
priority_queue<int> q;
map<int, int> cnt;
if (n >= 2)
{
q.push(n);
cnt[n] ++ ;
}
while (q.size())
{
auto t = q.top();
q.pop();
ans += t * cnt[t];
if (t % 2 == 0 && t / 2 >= 2)
{
if (cnt[t / 2] == 0) q.push(t / 2);
cnt[t / 2] += 2 * cnt[t];
}
else if (t % 2 != 0 && t / 2 >= 2)
{
if (cnt[t / 2] == 0) q.push(t / 2);
if (cnt[t / 2 + 1] == 0) q.push(t / 2 + 1);
cnt[t / 2] += cnt[t];
cnt[t / 2 + 1] += cnt[t];
}
else if (t % 2 != 0 && t / 2 + 1 >= 2)
{
if (cnt[t / 2 + 1] == 0) q.push(t / 2 + 1);
cnt[t / 2 + 1] += cnt[t];
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
第一次自己能很快想出d的思路,来源于一场牛客,也是类似的状态转移,但没有办法用dp做的问题,以后遇到这样的问题直接跑dijkstra吧,bfs可能会t
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n;
cin >> n;
vector<int> a(n), b(n), x(n);
for (int i = 1; i <= n - 1; i ++ ) cin >> a[i] >> b[i] >> x[i];
priority_queue<PII, vector<PII>, greater<PII>> q;
q.push({0, 1});
vector<int> ans(n + 1, INF);
ans[1] = 0;
while (q.size())
{
auto t = q.top();
q.pop();
int ver = t.second, value = t.first;
if (ans[ver + 1] > value + a[ver])
{
ans[ver + 1] = value + a[ver];
if (ver + 1 != n) q.push({ans[ver + 1], ver + 1});
}
if (ans[x[ver]] > value + b[ver])
{
ans[x[ver]] = value + b[ver];
if (x[ver] != n) q.push({ans[x[ver]], x[ver]});
}
}
cout << ans[n] << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
好激动!第一次没看题解自己写出来e(开心 ovo
看完题目脑子里就是区间修改+单点求和,所以直接用树状数组就可以啦,线段树也没问题,因为树状数组用的不太熟所以这一题用树状数组来写的
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
int tr[N];
inline int lowbit(int x)
{
return x & -x;
}
void add(int pos, int x)
{
for (int i = pos; i < N; i += lowbit(i)) tr[i] += x;
}
int query(int pos)
{
int res = 0;
for (int i = pos; i >= 1; i -= lowbit(i)) res += tr[i];
return res;
}
void solve()
{
int n, m;
cin >> n >> m;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) add(i, a[i] - a[i - 1]);
vector<int> b(m + 1);
for (int i = 1; i <= m; i ++ ) cin >> b[i], b[i] += 2;
for (int i = 1; i <= m; i ++ )
{
int cnt = query(b[i] - 1);
add(b[i] - 1, -cnt);
add(b[i], cnt);
add(b[i], 1);
if (b[i] + cnt - 1 <= n) add(b[i] + cnt, -1);
else
{
add(1, cnt / n);
add(n + 1, -(cnt / n));
cnt %= n;
add(1, 1);
add(1 + cnt, -1);
}
}
for (int i = 1; i <= n; i ++ ) cout << query(i) << ' ';
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
已知面积和底边,我们可以求出高h,现在我们的目的就是求距离已知的直线距离为h的直线有无解,扩欧就可以解决
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
int exgcd(int a, int b, int &x, int &y) // 扩展欧几里得
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
int r = exgcd(b, a % b, x, y);
int temp = y;
y = x - (a / b) * y;
x = temp;
return r; // 得到a b的最大公因数
}
void solve()
{
int a, b;
cin >> a >> b;
int x, y;
int tmp = exgcd(-b, a, x, y);
if (2 % tmp != 0) cout << -1 << '\n';
else
{
if (x == 0 && a == 0) swap(x, y);
if (y == 0 && b == 0) swap(x, y);
cout << x * 2 / tmp << ' ' << y * 2 / tmp << '\n';
return;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
还是没有养成注意数据范围的习惯,看见点数很少的时候应该直接往floyd上面想
然后考虑到需要判断每个点是否经过,于是往状压dp上想,一位代表一个点,这一位为1就说明已经经过该点
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, m;
cin >> n >> m;
vector<vector<int>> d(n + 1, vector<int>(n + 1, INF));
for (int i = 1; i <= n; i ++ ) d[i][i] = 0;
for (int i = 1; i <= m; i ++ )
{
int u, v, w;
cin >> u >> v >> w;
d[u][v] = w;
}
for (int k = 1; k <= n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
vector<vector<int>> dp((1 << n), vector<int>(n + 1, INF));
for (int i = 1; i <= n; i ++ ) dp[(1 << (i - 1))][i] = 0;
for (int bit = 1; bit < (1 << n); bit ++ )
{
for (int i = 1; i <= n; i ++ )
{
if ((bit >> (i - 1)) & 1 == 0) continue;
if (dp[bit][i] == INF) continue;
for (int j = 1; j <= n; j ++ )
{
if (((bit >> (j - 1)) & 1) == 1) continue;
if (d[i][j] == INF) continue;
dp[bit | (1 << (j - 1))][j] = min(dp[bit | (1 << (j - 1))][j], dp[bit][i] + d[i][j]);
}
}
}
int ans = INF;
for (int i = 1; i <= n; i ++ ) ans = min(ans, dp[(1 << n) - 1][i]);
if (ans == INF) cout << "No" << '\n';
else cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
水题
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
int flag;
for (int i = 1; i <= n; i ++ )
{
int x; cin >> x;
if (x == -1) flag = i;
else a[x] = i;
}
cout << flag << ' ';
int idx = flag;
while (a[idx])
{
cout << a[idx] << ' ';
idx = a[idx];
}
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
真是煞笔了花了一个多小时写一道前缀和,一开始给x的地方定义成无穷大,后来才发现如果一排全都是x,无穷大不断累加是会爆longlong的,之后要注意这一点
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, m, k, ans = INF;
cin >> n >> m >> k;
vector<vector<int>> g(n + 1, vector<int>(m + 1));
vector<vector<int>> x(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
char c; cin >> c;
if (c == 'x') x[i][j] = 1;
else if (c == '.') g[i][j] = 1;
}
vector<vector<int>> pre1(n + 1, vector<int>(m + 1));
vector<vector<int>> x1(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
x1[i][j] = x1[i][j - 1] + x[i][j];
pre1[i][j] = pre1[i][j - 1] + g[i][j];
}
for (int i = 1; i <= n; i ++ )
for (int j = k; j <= m; j ++ )
if (x1[i][j] - x1[i][j - k] != 0) continue;
else ans = min(ans, pre1[i][j] - pre1[i][j - k]);
vector<vector<int>> pre2(n + 1, vector<int>(m + 1));
vector<vector<int>> x2(n + 1, vector<int>(m + 1));
for (int j = 1; j <= m; j ++ )
for (int i = 1; i <= n; i ++ )
{
x2[i][j] = x2[i - 1][j] + x[i][j];
pre2[i][j] = pre2[i - 1][j] + g[i][j];
}
for (int j = 1; j <= m; j ++ )
for (int i = k; i <= n; i ++ )
if (x2[i][j] - x2[i - k][j] != 0) continue;
else ans = min(ans, pre2[i][j] - pre2[i - k][j]);
if (ans == INF) cout << -1 << '\n';
else cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}