花了大半天学了树套树(树状数组套主席树部分),题目还没有完全做完,明天继续做完剩下的一题和再往后学一下线段树套平衡树,代码能力好弱啊啊,今天把离散化写假了导致调了好久好久。目前还在坚持每天一场vp或者集训队的训练赛,希望思维上能尽快回到期末月前的状态。
昨天集美大学的校赛出到G,今天从H开始补。
(J线段树啊啊啊今天不补了,最近写数据结构写得头昏脑涨想创飞全人类qaq
题目链接
最大情况就是出现0和9,每100个数一定会出现一次90,所以如果l和r的差值大于100的话,就把范围缩小到100个数之内就好了
#include
using namespace std;
#define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
void solve()
{
int l, r;
cin >> l >> r;
if (l > r) swap(l, r);
if (r - l >= 100)
{
for (int i = l; i <= r; i ++ )
{
if (i % 100 == 90)
{
cout << i << '\n';
return;
}
}
}
else
{
int ans = 0;
string anss = to_string(l);
for (int i = l; i <= r; i ++ )
{
string ss = to_string(i);
char maxx = ss[0], minn = ss[0];
for (int j = 0; j < ss.size(); j ++ )
{
maxx = max(maxx, ss[j]);
minn = min(minn, ss[j]);
}
if (maxx - minn > ans)
{
ans = maxx - minn;
anss = ss;
}
}
cout << anss << '\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;
using i128 = __int128_t;
typedef pair<int, int> PII;
void solve()
{
int n, m;
cin >> n >> m;
vector<vector<int>> g(m + 1, vector<int>(n + 1));
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
cin >> g[j][i];
int ans = 0;
for (int i = 1; i <= m; i ++ )
{
sort(g[i].begin(), g[i].end());
vector<int> pre(n + 1);
for (int j = 1; j <= n; j ++ ) pre[j] = pre[j - 1] + g[i][j];
for (int j = 1; j <= n; j ++ )
{
ans += g[i][j] * (n - 1) - pre[j - 1] + (pre[n] - pre[j] - g[i][j] * (n - 1));
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
vp的时候没想出来,如果两个数位数不相同的话,直接取和l的位数一样,每一位全是9的数即可;如果位数相同,l和r分别判断:每次取前缀加上后面每一位0-9(讲的好乱)看代码好了
本质上能这么构造的原因是,先确定了前缀,后面未确定的数字取一样的和取不同的都是一样的,因为(这里只看最小值)比如说取1222和1111,反正前面的1222都有1了,2在最小值方面起不到任何作用,所以和取1111的效果是一样的
#include
using namespace std;
#define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
void get(vector<int> &v, int x)
{
while (x)
{
v.push_back(x % 10);
x /= 10;
}
reverse(v.begin(), v.end());
}
void solve()
{
int l, r;
cin >> l >> r;
vector<int> lv, rv;
get(lv, l), get(rv, r);
if (lv.size() != rv.size())
{
int ans = 0;
while (ans < l) ans = ans * 10 + 9;
cout << ans << '\n';
return;
}
else
{
int ans = 10;
int haha;
function<void(int, vector<int>)> check = [&](int x, vector<int> v)
{
int maxx = 0, minn = 10;
for (auto i : v)
{
maxx = max(maxx, i);
minn = min(minn, i);
}
if (maxx - minn < ans)
{
ans = maxx - minn;
haha = x;
}
};
check(l, lv), check(r, rv);
function<void(vector<int>)> work = [&](vector<int> v)
{
int tmp = 0;
for (int i = 0; i < v.size(); i ++ )
{
for (int j = 0; j <= 9; j ++ )
{
int res = tmp;
for (int k = i; k < v.size(); k ++ ) res = res * 10 + j;
if (res < l || res > r) continue;
vector<int> temp;
get(temp, res);
check(res, temp);
}
tmp = tmp * 10 + v[i];
}
};
work(lv), work(rv);
cout << haha << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
从这道题得到的一个教训就是往函数里传vector,以后还是都加上引用吧,说不准啥时候就会t得很惨
这道题告诉我们的一个贡献问题的思路,当贡献不好累加时就考虑从最大的贡献开始减去不符合情况的部分
#include
using namespace std;
#define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
vector<int> info[N][2];
void solve()
{
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i ++ )
{
int x; cin >> x;
info[x][i & 1].push_back(i);
}
if (k == 1)
{
cout << 0 << '\n';
return;
}
int ans = (k / 2) * (n - k + 1);
auto find = [&](vector<int>& v, int l, int r)
{
return upper_bound(v.begin(), v.end(), r) - lower_bound(v.begin(), v.end(), l);
};
for (int i = 1; i <= 2e5; i ++ )
{
for (int j = 0; j < 2; j ++ )
{
for (auto tmp : info[i][j])
{
int l = max((i64)1, max((2 + 2 * (k / 2) - tmp), (tmp + 1 - k)));
int r = min(tmp - 1, 2 * n - 2 * (k / 2) - tmp);
if (l <= r) ans -= find(info[i][j], l, r);
}
}
}
cout << ans;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
现在一看当时没做真的很不应该,真的挺简单的一道题啊啊啊,Dijkstra中的dist多加一维存一下颜色就可以了
#include
using namespace std;
// #define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
const int N = 100010;
struct Edge
{
int v, col, w;
};
struct Node
{
int v, d, c;
bool operator> (const Node &tmp) const
{
if (d != tmp.d) return d > tmp.d;
else return c > tmp.c;
}
};
void solve()
{
int n, m, l, base;
cin >> n >> m >> l >> base;
vector<vector<Edge>> g(n + 1);
for (int i = 0; i < m; i ++ )
{
int u, v, col, w;
cin >> u >> v >> col >> w;
g[u].push_back({v, col, w});
}
vector<vector<int>> dist(n + 1, vector<int>(l + 1, 0x3f3f3f3f));
priority_queue<Node, vector<Node>, greater<Node>> q;
for (int i = 1; i <= l; i ++ )
{
dist[1][i] = 0;
q.push({1, 0, i});
}
while (q.size())
{
auto t = q.top();
q.pop();
int ver = t.v, color = t.c, dd = t.d;
for (int i = 0; i < g[ver].size(); i ++ )
{
int j = g[ver][i].v, cc = g[ver][i].col, w = g[ver][i].w;
if (cc == color)
{
if (dist[j][cc] > dist[ver][cc] + w)
{
dist[j][cc] = dist[ver][cc] + w;
q.push({j, dist[j][cc], cc});
}
}
else
{
if (dist[j][cc] > dist[ver][color] + w * base)
{
dist[j][cc] = dist[ver][color] + w * base;
q.push({j, dist[j][cc], cc});
}
}
}
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= l; i ++ ) ans = min(ans, dist[n][i]);
if (ans != 0x3f3f3f3f) cout << ans << '\n';
else cout << -1 << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
还是很板的一题:dp+二分
#include
using namespace std;
#define int long long
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
const int N = 10010;
void solve()
{
int n; cin >> n;
vector<int> dp(N, 1e18);
dp[0] = 0;
for (int i = 1; i <= n; i ++ )
{
int w, v;
cin >> w >> v;
for (int j = N - 1; j >= v; j -- )
{
dp[j] = min(dp[j], dp[j - v] + w);
}
}
for (int i = N - 2; i >= 0; i -- )
{
dp[i] = min(dp[i], dp[i + 1]);
}
int q; cin >> q;
while (q -- )
{
int maxx; cin >> maxx;
int ans = upper_bound(dp.begin(), dp.end(), maxx) - dp.begin() - 1;
cout << ans << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}