记录一个训练赛踩的大坑:往函数里传vector一定要加引用!犯了三次的错误还是记不住,服了,一道题调了一个小时。
题目链接
从后往前看,每个数加上前面的所有数能不能超过后一个数,一旦有一个数不行了就直接输出前面的数即可(注意开longlong啊啊啊)
#include
using namespace std;
typedef pair<int, int> PII;
#define int long long
void solve()
{
int n;
cin >> n;
vector<PII> a(n + 1);
for (int i = 1; i <= n ;i ++)
{
cin >> a[i].first;
a[i].second = i;
}
sort(a.begin(), a.end());
vector<int> pre(n + 1);
for (int i = 1; i <= n; i ++) pre[i] = pre[i -1 ] +a[i].first;
vector<int> per;
per.push_back(a[n].second);
for (int i = n - 1; i > 0; i -- )
{
if (pre[i] >= a[i + 1].first) per.push_back(a[i].second);
else break;
}
sort(per.begin(), per.end());
cout << per.size() << '\n';
for (auto i : per) cout << i << ' ';
cout << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- )
{
solve();
}
}
题目链接
太毒瘤了这题赛时想了老半天
先记录下分子上每个数字出现的次数然后合并,比如说3个2!就合并成一个3!这样,看最后能不能都合并成x!的倍数即可
#include
using namespace std;
typedef pair<int, int> PII;
#define int long long
void solve()
{
int n, x;
cin >> n >> x;
map<int, int> mp;
for (int i = 0; i < n; i ++ )
{
int kk; cin >> kk;
mp[kk] ++ ;
}
for (auto &i : mp)
{
if (i.first == x)
{
cout << "YES\n";
return;
}
if (i.second % (i.first + 1) != 0)
{
cout << "NO\n";
return;
}
else
{
mp[i.first + 1] += i.second / (i.first + 1);
}
}
cout << "YES\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
晚上补题的时候发现比想象中简单,好可惜赛时没做这题啊
n个顶点n条边的图我们叫做基环树,可以想象它长这样:
我们先记录环上的点,每个环上的点引出去的子树中,两点之间都只有一条路径,然后子树和其他点之间都有两条路径(因为有个环),可以循环计算每个子树,答案累加即可
#include
using namespace std;
typedef pair<int, int> PII;
#define int long long
void solve()
{
int n;
cin >> n;
vector<vector<int>> g(n + 1);
vector<int> in(n + 1);
for (int i = 0 ;i < n; i ++ )
{
int a, b;
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
in[a] ++ , in[b] ++ ;
}
queue<int> q;
for (int i = 1; i <= n; i ++ )
{
if (in[i] == 1) q.push(i);
}
while (q.size())
{
auto t = q.front();
q.pop();
for (int i = 0; i < g[t].size(); i ++ )
{
int j = g[t][i];
in[j] -- ;
if (in[j] == 1) q.push(j);
}
}
vector<int> huan;
vector<int> st(n + 1);
for (int i = 1; i <= n; i ++ )
{
if (in[i] > 1)
{
huan.push_back(i);
st[i] = true;
}
}
int ans = 0, sumtmp, sum = 0;
vector<bool> visited(n + 1);
function<void(int, int)> dfs = [&](int u, int fa)
{
sumtmp ++ ;
if (visited[u]) return;
visited[u] = true;
for (int i = 0; i < g[u].size(); i ++ )
{
int j = g[u][i];
if (j == fa || visited[j] || st[j]) continue;
dfs(j, u);
}
return;
};
for (auto i : huan)
{
sumtmp = 0;
dfs(i, -1);
ans += sumtmp * (sumtmp - 1) / 2;
ans += (sumtmp - 1) * (n - sumtmp - sum) * 2;
sum += sumtmp - 1;
}
ans += huan.size() * (huan.size() - 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();
}
}
题目链接
受到之前cf有场div2的启发,当xy模mod余数相同,等价于x与y之差是mod的倍数
所以首先判断是否全为偶数,如果全是偶数直接除以2就可以
如果不是偶数,最差的情况是除以2,有的是1有的是0,然后再看一下能不能让所有数全部相同,我们就计算相邻两数之差取gcd,如果gcd是1就不能让所有数全相同,不是1直接除以那个gcd就可以让所有数全相同了
#include
using namespace std;
typedef pair<int, int> PII;
#define int long long
void solve()
{
int n;
cin >> n;
vector<int> a(n);
int cnt0 = 0, cnt1 = 0;
for (int i = 0; i < n; i ++ )
{
cin >> a[i];
if (a[i] % 2 == 0 ) cnt0 ++ ;
else cnt1 ++ ;
}
if (cnt0 == n) cout << 1 << '\n';
else
{
sort(a.begin(), a.end());
int tmp = a[1] - a[0];
for (int i = 2; i < n; i ++ ) tmp = __gcd(tmp, a[i] - a[i - 1]);
if (tmp == 1) cout << 2 << '\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+bitset优化
如果我们可以到第 i 张牌,那我们得到的积分就是 a[1] + a[2] + … + a[i] - (i - 1),为什么是这么多呢,因为前面 i 张牌得到的积分是 a[1] 加到 a[i],然后我们为了到第 i 张,还需要花费 i - 1(第一张思免费送给我们的)
现在问题就变成了判断能否到 i 的位置,用bitset记录,如果可以到 i 的位置就把 dp[i] 赋为 1,到第 i 位就更新ans,要注意更新完之后要把 dp[i] 恢复成 0(因为有后效性,如果不清空,后面的操作就会把当前位的1往后挪)
#include
using namespace std;
typedef pair<int, int> PII;
#define int long long
const int N = 200010;
void solve()
{
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
bitset<N> dp;
dp[0] = 1;
n <<= 1;
int sum = 0, ans = 0;
for (int i = 0; i < n; i ++ )
{
if (i < n / 2)
{
dp |= (dp << a[i]);
sum += a[i];
}
if (dp[i])
{
ans = max(ans, sum - i);
dp[i] = 0;
}
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
用Dijkstra做的,dfs应该也可以
#include
using namespace std;
typedef pair<int, int> PII;
void solve()
{
int n, s;
cin >> n >> s;
vector<int> a(n + 1), b(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 1; i <= n; i ++ ) cin >> b[i];
vector<vector<int>> g(n + 1);
int last = -1;
for (int i = 1; i <= n; i ++ )
{
if (a[i] == 1 && last != -1) g[last].push_back(i), last = i;
else if (a[i] == 1) last = i;
}
last = -1;
for (int i = n; i > 0; i -- )
{
if (b[i] == 1 && last != -1) g[last].push_back(i), last = i;
else if (b[i] == 1) last = i;
}
priority_queue<PII, vector<PII>, greater<PII>> q;
vector<int> dist(n + 1, 0x3f3f3f3f);
dist[1] = 0;
q.push(make_pair(0, 1));
vector<bool> st(n + 1);
while (q.size())
{
auto t = q.top();
q.pop();
int dd = t.first, ver = t.second;
if (st[ver]) continue;
st[ver] = true;
for (int i = 0; i < g[ver].size(); i ++ )
{
int j = g[ver][i];
if (dist[j] > dist[ver] + 1)
{
dist[j] = dist[ver] + 1;
q.push(make_pair(dist[j], j));
if (j == s)
{
cout << "YES\n";
return;
}
}
}
}
if (dist[s] == 0x3f3f3f3f) cout << "NO\n";
else cout << "YES\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
while (t -- )
{
solve();
}
}
题目链接
二分+树状数组
#include
using namespace std;
typedef pair<int, int> PII;
#define int long long
inline int lowbit(int x)
{
return x & -x;
}
void solve()
{
int n, m, w;
cin >> n >> m >> w;
vector<int> tr(n + 1), a(n + 1);
int minn = 0x3f3f3f3f, maxx = 0;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i];
maxx = max(maxx, a[i]);
minn = min(minn, a[i]);
}
auto add = [&](int i, int x, vector<int> &tr)
{
for (; i <= n; i += lowbit(i))
tr[i] += x;
};
for (int i = 1; i <= n; i ++ ) add(i, a[i] - a[i - 1], tr);
vector<int> notav;
auto presum = [&](int i, vector<int> &tmp)
{
int res = 0;
for (; i > 0; i -= lowbit(i)) res += tmp[i];
return res;
};
auto check = [&](int mid)
{
vector<int> tmp(tr);
int cnt = 0;
for (int i = 1; i <= n; i ++ )
{
if (presum(i, tmp) < mid)
{
if (cnt == m) return false;
add(i, 1, tmp);
add(i + w, -1, tmp);
cnt ++ ;
i -- ;
}
}
return true;
};
int l = minn, r = 1e10;
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();
}
}
题目链接
大水题
#include
using namespace std;
void solve()
{
string s;
cin >> s;
int ans = 0;
for (int i = 0; i < s.size(); i ++ )
{
if (s[i] == 'Q')
{
for (int j = i + 1; j < s.size(); j ++ )
{
if (s[j] == 'A')
{
for (int k = j + 1; k < s.size(); k ++ )
{
if (s[k] == 'Q')
{
ans ++ ;
continue;
}
}
}
}
}
}
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
while (t -- )
{
solve();
}
}