期末考试期间没怎么刷题,空下来就看看某乎,看了不少退役ACMer的记录和建议,觉得自己对于题目的思考还是太浅了,很多题目搞懂就过去了(甚至没有搞懂也就过去了),也没有去思考到底这些想法是怎么来的,这期间看到的一句话对我感触很深,就是要从大量题目的偶然中寻找一定的必然,所以在寒假期间记录一下想法以及督促自己训练。
题目链接
遍历每个条件,维护满足已遍历条件的左右端点即可,条件3记录在set里最后再判断处理
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
void solve()
{
int n;
cin >> n;
int l = -1e9, r = 1e9;
set<int> st;
for (int i = 0; i < n; i ++ )
{
int a, x;
cin >> a >> x;
if (a == 1) l = max(x, l);
else if (a == 2) r = min(r, x);
else if (a == 3) st.insert(x);
}
if (l > r) cout << 0 << '\n';
else
{
int ans = r - l + 1;
for (auto t : st)
{
if (t >= l && t <= r) ans -- ;
}
cout << ans << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
这题犯的错误就是读题不够仔细,首先没有注意到数组中只有正数,还去特判了负数,其次就是初始化最小值的时候一定要注意数据范围,一开始初始化成-1e8直接wa了三发,实际要到-1e9才可以qaq
思路就是暴力枚举第一个人需要从大到小删掉多少个数,利用一下前缀和,维护最优情况就可以
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
void solve()
{
int n, a, b;
cin >> n >> a >> b;
vector<int> num(n + 1);
int sum = 0;
for (int i = 1; i <= n; i ++ )
{
cin >> num[i];
sum += num[i];
}
if (n == 1)
{
cout << 0 << '\n';
return;
}
sort(num.begin(), num.end());
vector<int> pre(n + 1);
for (int i = 1; i <= n; i ++ ) pre[i] = pre[i - 1] + num[i];
int temp = -1e18;
for (int i = 0; i <= a; i ++ )
{
int tmp1 = pre[n] - pre[n - i];
int tmp2 = pre[n - i] - pre[max((i64)0, n - i - b)];
temp = max(temp, sum - tmp1 - tmp2 * 2);
}
cout << temp << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
这题中学到的结论是:两个数模上同一个数m的余数相同,那么这两个数的差值一定是m的倍数
#include
using namespace std;
// #define int long long
using i64 = long long;
typedef pair<int, int> PII;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
int ans = 0;
for (int i = 1; i <= n; i ++ )
{
if (n % i != 0) continue;
int tmp = 0;
for (int j = 0; j + i < n; j ++ )
{
tmp = __gcd(tmp, abs(a[j] - a[j + i]));
}
ans += (tmp != 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();
}
}
题目链接
遇到包含重复区间且数据很大,无法线性处理的情况,可以考虑通过取模将重复的大数据映射到小范围内
#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, q;
cin >> n >> q;
map<i64, i64> mp;
vector<pair<i128, i128>> cp;
i128 len = 0;
for (int i = 0; i < n; i ++ )
{
int op, x;
cin >> op >> x;
if (op == 1) mp[ ++ len] = x;
else
{
if (len > 1e18) continue;
i128 tmp = len;
len = len * (x + 1);
if (len > 1e18) len = 1e18 + 1;
cp.push_back(make_pair(len, tmp));
}
}
while (q -- )
{
i64 k; cin >> k;
while (!mp.count(k))
{
int pos = lower_bound(cp.begin(), cp.end(), make_pair((i128)k, (i128)0)) - cp.begin();
k = k % cp[pos].second;
if (k == 0) k = cp[pos].second;
}
cout << mp[k] << ' ';
}
cout << '\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
const int mod = 998244353;
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
void solve()
{
int n, k;
cin >> n >> k;
vector<vector<int>> dp(n + 1, vector<int>(k + 1));
for (int i = 0; i <= k; i ++ ) dp[0][i] = 1;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= k; j ++ )
{
dp[i][j] = 0;
for (int p = 0; i - j * p >= 0 && j + p - 1 <= k; p ++ )
{
dp[i][j] = (dp[i][j] + dp[i - j * p][p]) % mod;
}
}
}
int ans = 0;
for (int i = 0; i <= k; i ++ ) ans = (ans + dp[n][i]) % mod;
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
第一次做2500的题,发现没有我想象中的困难,算法本质上还是简单的,主要是思路要清晰以及代码能力要强
多源最短路(可能不是严格的多源最短路)(就是起点有很多,但是最短路径的长度只存储离该点最近的起点的长度)用BFS即可,先將所有起点都存进queue,然后和普通情况一样做(这和超级源点的思路也是一样的,即设置一个超级源点,向所有起点连一条权值是0的边(不过这种二维地图的图论,超级源点好像不太好做,所以像这样直接把所有起点传进去就可以了))
#include
using namespace std;
// #define int long long
const int mod = 998244353;
using i64 = long long;
using i128 = __int128_t;
typedef pair<int, int> PII;
int dx[8] = {0, 0, 1, -1, 1, 1, -1, -1};
int dy[8] = {1, -1, 0, 0, -1, 1, 1, -1};
void solve()
{
int n, m, qq;
cin >> n >> m >> qq;
vector<string> g(n);
for (int i = 0; i < n; i ++ ) cin >> g[i];
queue<PII> q;
vector<vector<int>> dist(n, vector<int>(m, 1e9));
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (g[i][j] == 'v')
{
q.push(make_pair(i, j));
dist[i][j] = 0;
}
while (q.size())
{
auto t = q.front();
q.pop();
int x = t.first, y = t.second;
for (int i = 0; i < 4; i ++ )
{
int nx = x + dx[i], ny = y + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if (dist[nx][ny] > dist[x][y] + 1)
{
dist[nx][ny] = dist[x][y] + 1;
q.push(make_pair(nx, ny));
}
}
}
while (qq -- )
{
int x, y;
cin >> x >> y;
x -- , y -- ;
function<bool(int)> check = [&](int mid)
{
vector<vector<int>> st(n, vector<int>(m));
queue<PII> q;
q.push(make_pair(x, y));
st[x][y] = 1;
while (q.size())
{
auto t = q.front();
q.pop();
int xx = t.first, yy = t.second;
for (int i = 0; i < 4; i ++ )
{
int nx = xx + dx[i], ny = yy + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if (g[nx][ny] == '#') continue;
if (st[nx][ny]) continue;
if (dist[nx][ny] < mid) continue;
st[nx][ny] = 1;
q.push(make_pair(nx, ny));
}
}
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ )
if (g[i][j] == '#')
{
st[i][j] = 2;
q.push(make_pair(i, j));
}
while (q.size())
{
auto t = q.front();
q.pop();
int xx = t.first, yy = t.second;
if (xx <= 0 || xx >= n - 1 || yy <= 0 || yy >= m - 1) return false;
for (int i = 0; i < 8; i ++ )
{
int nx = xx + dx[i], ny = yy + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if (st[nx][ny]) continue;
st[nx][ny] = 2;
q.push(make_pair(nx, ny));
}
}
return true;
};
int l = 0, r = dist[x][y];
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout << r << '\n';
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}