注意到值域很小,所以可以对每种 w w w 数只考虑 ≤ w \le w ≤w 的边的连通块个数。维护一个大小为 2 n 2n 2n 的并查集,表示第 i i i 列和第 i + 1 i+1 i+1 列的连通性。考虑右移一列并查集的变化,如果在之前的并查集合并了集合 u + n , v + n u+n, v+n u+n,v+n ,那么在新的并查集上 u u u 和 v v v 会变得连通。如果它们已经连通了,这条边就没用了;否则它们可能新增连通性,对后面有影响,以此类推即可。
#include
using namespace std;
const int MAX = 30;
class dsu {
public:
vector<int> p;
int n;
dsu(int n): n(n) {
p.resize(n);
for (int i = 0; i < n; ++i) {
p[i] = i;
}
}
inline int find(int x) {
while (x != p[x]) {
x = p[x] = p[p[x]];
}
return x;
}
inline bool unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
} else {
p[x] = y;
return true;
}
}
};
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m, q;
cin >> n >> m >> q;
vector<vector<pair<int, int>>> edges(MAX);
while (q--) {
int from, to, cost;
cin >> from >> to >> cost;
--from;
--to;
for (int i = cost; i < MAX; ++i) {
edges[i].emplace_back(from, to);
}
}
vector<long long> ans(m);
for (int w = 0; w < MAX; ++w) {
dsu p(n * 2);
vector<long long> tag(m);
vector<pair<int, int>> useful;
for (auto e : edges[w]) {
int x = p.find(e.first), y = p.find(e.second + n);
if (x > y) {
swap(x, y);
}
if (p.unite(x, y)) {
++tag[0];
if (x >= n && y >= n) {
useful.emplace_back(x - n, y - n);
}
}
}
for (int i = 1; i < m && !useful.empty(); ++i) {
vector<pair<int, int>> new_useful;
for (auto e : useful) {
int x = p.find(e.first), y = p.find(e.second);
if (x > y) {
swap(x, y);
}
if (p.unite(x, y)) {
if (x >= n && y >= n) {
new_useful.emplace_back(x - n, y - n);
}
} else {
--tag[i];
}
}
swap(useful, new_useful);
}
for (int i = 1; i < m; ++i) {
tag[i] += tag[i - 1];
}
for (int i = 1; i < m; ++i) {
tag[i] += tag[i - 1];
}
for (int i = 0; i < m; ++i) {
ans[i] += (long long) n * (i + 2) - 1 - tag[i];
}
}
for (int i = 0; i < m; ++i) {
cout << ans[i] << "\n";
}
return 0;
}
考虑一个排列,用尽量少的段去覆盖它,分两种情况讨论:
所以 f ( n ) = ∑ k ≥ 2 ∏ ∑ i = 1 k a i = n f ( a i ) + ∑ k ≥ 4 ∏ ∑ i = 1 k a i = n f ( a i ) f(n) = \sum_{k\ge 2} \prod_{\sum_{i=1}^k a_i = n} f(a_i) + \sum_{k\ge 4} \prod_{\sum_{i=1}^k a_i = n} f(a_i) f(n)=∑k≥2∏∑i=1kai=nf(ai)+∑k≥4∏∑i=1kai=nf(ai)
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int n, md;
cin >> n >> md;
auto add = [&](int &x, int y) {
x += y;
if (x >= md) {
x -= md;
}
};
auto mul = [&](int x, int y) {
return (long long) x * y % md;
};
vector<vector<int>> sum(4, vector<int>(n + 1));
vector<int> dp(n + 1);
dp[1] = sum[0][1] = 1;
for (int i = 2; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
for (int k = 3; k; --k) {
add(sum[k][i], mul(dp[j], sum[k - 1][i - j]));
if (k == 3) {
add(sum[k][i], mul(dp[j], sum[k][i - j]));
}
}
}
dp[i] = sum[3][i];
for (int k = 3; k; --k) {
add(dp[i], sum[k][i]);
}
sum[0][i] = dp[i];
}
for (int i = 1; i <= n; ++i) {
cout << dp[i] << "\n";
}
return 0;
}
注意到 4 , 9 , 25 , 49 4, 9, 25, 49 4,9,25,49 的倍数的 μ \mu μ 一定为 0 0 0 ,所以枚举余数爆搜即可。对于一个合法的序列要搜索的东西不多,加个卡时判无解即可。
#include
using namespace std;
const int N = 200;
const int MAX = 1e9;
const int SQ = sqrt(MAX);
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
string pattern;
for (int i = 0; i < 10; ++i) {
string s;
cin >> s;
pattern += s;
}
int ans = MAX - N + 2;
vector<bool> isprime(SQ + 1, true);
vector<int> primes;
for (int i = 2; i <= SQ; ++i) {
if (isprime[i]) {
primes.push_back(i);
for (int j = i + i; j <= SQ; j += i) {
isprime[j] = false;
}
}
}
bool ed = false;
auto solve = [&](int l) {
if (clock() > CLOCKS_PER_SEC * 0.9) {
ed = true;
return;
}
int r = l + N - 1;
string s(N, '1');
for (auto p : primes) {
if (p * p > r) {
break;
}
int q = p * p;
for (int i = (l + q - 1) / q * q; i <= r; i += q) {
s[i - l] = '0';
if (pattern[i - l] == '1') {
return;
}
}
}
if (s == pattern) {
ans = l;
}
};
for (int i = 1; i <= 44100; ++i) {
bool ok = true;
for (int j = 0; j < N; ++j) {
if (((i + j) % 4 == 0 || (i + j) % 9 == 0 || (i + j) % 25 == 0 || (i + j) % 49 == 0) && pattern[j] == '1') {
ok = false;
break;
}
}
if (ok) {
for (int j = i; j < ans; j += 44100) {
solve(j);
if (ed) {
break;
}
}
}
if (ed) {
break;
}
}
if (ans == MAX - N + 2) {
ans = -1;
}
cout << ans << "\n";
return 0;
}
判 n n n 和 m m m 大小关系。
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int tt;
cin >> tt;
while (tt--) {
int n, m;
cin >> n >> m;
cout << (n <= m ? "Yes" : "No") << "\n";
for (int i = 0; i < n + m; ++i) {
int x;
cin >> x;
}
}
return 0;
}
大概是要DP前缀最小值之类的东西,倒着DP一遍即可。
#include
using namespace std;
const int md = 998244353;
inline void add(int &x, int y) {
x += y;
if (x >= md) {
x -= md;
}
}
inline int mul(int x, int y) {
return (long long) x * y % md;
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
auto solve = [&](string s) {
reverse(s.begin(), s.end());
int n = s.size();
vector<int> f(n * 2 + 1), g(n * 2 + 1);
f[n] = 1;
for (auto c : s) {
vector<int> new_f(n * 2 + 1), new_g(n * 2 + 1);
if (c != 'V') {
for (int i = 0; i <= n * 2; ++i) {
if (f[i]) {
if (n <= i - 1) {
add(new_g[n], f[i]);
} else {
add(new_f[i - 1], f[i]);
}
}
if (g[i]) {
add(new_g[min(n, i - 1)], g[i]);
}
}
}
if (c != 'P') {
for (int i = 0; i <= n * 2; ++i) {
if (f[i]) {
add(new_f[i + 1], f[i]);
}
if (g[i]) {
add(new_g[i + 1], g[i]);
}
}
}
swap(f, new_f);
swap(g, new_g);
}
return make_pair(f, g);
};
string s, t;
cin >> s >> t;
pair<vector<int>, vector<int>> foo = solve(s);
pair<vector<int>, vector<int>> bar = solve(t);
int n = s.size(), m = t.size();
int ans = 0;
for (int i = 0; i <= n * 2; ++i) {
for (int j = 0; j <= m * 2; ++j) {
if (i + j > n + m) {
add(ans, mul(foo.first[i] + foo.second[i], bar.first[j] + bar.second[j]));
} else if (i + j == n + m) {
add(ans, mul(foo.first[i], bar.first[j]));
}
}
}
cout << ans << "\n";
return 0;
}
最短路一定在同一个平面上。
#include
using namespace std;
class point {
public:
int x, y, z;
point(int x = 0, int y = 0, int z = 0): x(x), y(y), z(z) {
}
point operator - (const point &b) const {
return point(x - b.x, y - b.y, z - b.z);
}
int operator * (const point &b) const {
return x * b.x + y * b.y + z * b.z;
}
int sqr() {
return *this * *this;
}
double len() {
return sqrt(sqr());
}
};
long long sqr(int x) {
return (long long) x * x;
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
cout.setf(ios::fixed);
cout.precision(10);
int tt;
cin >> tt;
while (tt--) {
point o, a, b;
int r;
cin >> o.x >> o.y >> o.z >> r;
cin >> a.x >> a.y >> a.z;
cin >> b.x >> b.y >> b.z;
if ((a - b).sqr() == 0 || (o - a) * (b - a) <= 0 || (o - b) * (a - b) <= 0) {
cout << (a - b).len() << "\n";
} else {
double h = sqrt((o - a).sqr() - (double) sqr((o - a) * (b - a)) / (a - b).sqr());
if (r <= h) {
cout << (a - b).len() << "\n";
} else {
double go_a = sqrt((o - a).sqr() - sqr(r));
double go_b = sqrt((o - b).sqr() - sqr(r));
double angle = atan2(sqrt((o - a).sqr() - h * h), h) + atan2(sqrt((o - b).sqr() - h * h), h) - atan2(go_a, r) - atan2(go_b, r);
cout << angle * r + go_a + go_b << "\n";
}
}
}
return 0;
}
特判掉 m = 1 m=1 m=1 的情况,无解当且仅当: n   m o d   k ≠ 0 n\bmod k\neq 0 nmodk̸=0 或 m k > n mk>n mk>n 或 c n t B < 2 m cnt_{B}<2m cntB<2m 。
考虑构造 m = 2 m=2 m=2 的解,找到 4 4 4 个 B B B ,假设是 k 1 , k 2 , k 3 , k 4 k1, k2, k3, k4 k1,k2,k3,k4 ,构造 ( k 1 , k 2 , k 3 + 1 , k 3 + 2 , ⋯   , k 4 − 1 ) (k1, k2, k3+1, k3+2, \cdots, k4-1) (k1,k2,k3+1,k3+2,⋯,k4−1) 和 $ (k1+1, k1+2, \cdots, k2-1, k3, k4)$ ,再将其他的按照   m o d   k \bmod k modk 的要求分配即可。如果找不到解,旋转一下就有解了。
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
while (tt--) {
int n, m, k;
string str;
cin >> n >> m >> k >> str;
vector<int> a(n);
int sum = 0;
for (int i = 0; i < n; ++i) {
a[i] = str[i] == 'B';
sum += a[i];
}
if (n % k || (long long) m * k > n || sum < m * 2) {
cout << "No" << "\n";
continue;
}
if (m == 1) {
bool ok = false;
for (int i = 0; i < n; ++i) {
if (a[i] && a[(i + 1) % n]) {
ok = true;
break;
}
}
if (ok) {
cout << "Yes" << "\n";
cout << n;
for (int i = 0; i < n; ++i) {
cout << " " << i;
}
cout << "\n";
} else {
cout << "No" << "\n";
}
continue;
}
cout << "Yes" << "\n";
for (int i = 0; i < n && sum > m * 2; ++i) {
if (a[i]) {
a[i] = 0;
--sum;
}
}
int k1 = -1, k2 = -1;
for (int i = 0; i < n; ++i) {
if (a[i]) {
if (k1 == -1) {
k1 = i;
} else if (k2 == -1) {
k2 = i;
}
}
}
vector<vector<int>> ans(m);
if (k == 1) {
int ptr = 0;
for (int i = 0; i < n; ++i) {
if (a[i]) {
ans[ptr++ >> 1].push_back(i);
} else {
ans[i > k1 && i < k2].push_back(i);
}
}
for (int i = 0; i < m; ++i) {
cout << ans[i].size();
for (auto x : ans[i]) {
cout << " " << x;
}
cout << "\n";
}
continue;
}
vector<bool> visit(n);
if (m & 1) {
if (k2 - k1 + 1 >= k) {
ans[m - 1].push_back(k1);
visit[k1] = true;
int cur = k - 2;
for (int i = k1 + 1; i < k2 && cur; ++i) {
if (!a[i]) {
ans[m - 1].push_back(i);
visit[i] = true;
--cur;
}
}
ans[m - 1].push_back(k2);
visit[k2] = true;
} else {
int cur = k - 2;
for (int i = 0; i < k1 && cur; ++i) {
if (!a[i]) {
ans[m - 1].push_back(i);
visit[i] = true;
--cur;
}
}
ans[m - 1].push_back(k1);
visit[k1] = true;
ans[m - 1].push_back(k2);
visit[k2] = true;
for (int i = k2 + 1; i < n && cur; ++i) {
if (!a[i]) {
ans[m - 1].push_back(i);
visit[i] = true;
--cur;
}
}
}
}
vector<vector<int>> candidates(m >> 1);
int ptr0 = 0, ptr1 = 0, remain = max(k * 2 - 4, 2);
for (int i = 0; i < n; ++i) {
if (!visit[i]) {
if (a[i]) {
candidates[ptr1++ >> 2].push_back(i);
} else {
candidates[ptr0].push_back(i);
if (!--remain) {
if (ptr0 + 1 == m >> 1) {
remain = n;
} else {
++ptr0;
remain = max(k * 2 - 4, 2);
}
}
}
}
}
auto add = [&](vector<int> p, int w) {
int k1 = -1, k2 = -1, k3 = -1, k4 = -1;
for (int i = 0; i < p.size(); ++i) {
if (a[p[i]]) {
if (k1 == -1) {
k1 = i;
} else if (k2 == -1) {
k2 = i;
} else if (k3 == -1) {
k3 = i;
} else if (k4 == -1) {
k4 = i;
}
}
}
int need = (2 * k - 2 - (k4 - k3 - 1) % k) % k;
for (int i = 0; i < p.size(); ++i) {
if (i == k1 || i == k2) {
ans[w].push_back(p[i]);
} else if (i == k3 || i == k4) {
ans[w + 1].push_back(p[i]);
} else if (i > k1 && i < k2) {
ans[w + 1].push_back(p[i]);
} else if (i > k3 && i < k4) {
ans[w].push_back(p[i]);
} else if (need) {
ans[w].push_back(p[i]);
--need;
} else {
ans[w + 1].push_back(p[i]);
}
}
if (need) {
ans[w].clear();
ans[w + 1].clear();
need = (2 * k - 2 - (k3 - k2 - 1) % k) % k;
for (int i = 0; i < p.size(); ++i) {
if (i == k1 || i == k4) {
ans[w].push_back(p[i]);
} else if (i == k2 || i == k3) {
ans[w + 1].push_back(p[i]);
} else if (i < k1 || i > k4) {
ans[w + 1].push_back(p[i]);
} else if (i > k2 && i < k3) {
ans[w].push_back(p[i]);
} else if (need) {
ans[w].push_back(p[i]);
--need;
} else {
ans[w + 1].push_back(p[i]);
}
}
}
};
for (int i = 0; i < m >> 1; ++i) {
add(candidates[i], i * 2);
}
for (int i = 0; i < m; ++i) {
cout << ans[i].size();
for (auto x : ans[i]) {
cout << " " << x;
}
cout << "\n";
}
}
return 0;
}
留坑,不打算填。
倒着DP。
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
int tt;
cin >> tt;
while (tt--) {
int n;
cin >> n;
vector<int> a(n), b(n), c(n);
for (int i = 0; i < n; ++i) {
cin >> a[i] >> b[i] >> c[i];
}
int m = n * (n + 1) / 2 + 1;
vector<vector<long long>> dp(n + 1, vector<long long>(m, -1));
dp[0][0] = 0;
for (int i = n - 1; ~i; --i) {
vector<vector<long long>> new_dp(n + 1, vector<long long>(m, -1));
for (int j = 0; j <= n; ++j) {
for (int k = 0; k < m; ++k) {
if (~dp[j][k]) {
new_dp[j + 1][k + j + 1] = max(new_dp[j + 1][k + j + 1], dp[j][k] + a[i]);
new_dp[j][k + j] = max(new_dp[j][k + j], dp[j][k] + (long long) b[i] * k);
new_dp[j][k + j] = max(new_dp[j][k + j], dp[j][k] + (long long) c[i] * j);
}
}
}
swap(dp, new_dp);
}
long long ans = 0;
for (int i = 0; i <= n; ++i) {
ans = max(ans, *max_element(dp[i].begin(), dp[i].end()));
}
cout << ans << "\n";
}
return 0;
}
求出SA,按照height从大到小合并维护答案即可。
#include
using namespace std;
template<typename T>
vector<int> suffix_array(const T &s, int n, int alpha) {
vector<int> a(n);
if (~alpha) {
vector<int> bucket(alpha);
for (int i = 0; i < n; ++i) {
++bucket[s[i]];
}
int sum = 0;
for (int i = 0; i < alpha; ++i) {
int add = bucket[i];
bucket[i] = sum;
sum += add;
}
for (int i = 0; i < n; ++i) {
a[bucket[s[i]]++] = i;
}
} else {
for (int i = 0; i < n; ++i) {
a[i] = i;
}
sort(a.begin(), a.end(), [&](const int &x, const int &y) {
return s[x] < s[y];
});
}
vector<int> sorted_by_second(n);
vector<int> ptr_group(n);
vector<int> new_group(n);
vector<int> group(n);
group[a[0]] = 0;
for (int i = 1; i < n; ++i) {
group[a[i]] = group[a[i - 1]] + (s[a[i]] != s[a[i - 1]]);
}
int step = 1;
while (group[a[n - 1]] < n - 1) {
int ptr = 0;
for (int i = n - step; i < n; ++i) {
sorted_by_second[ptr++] = i;
}
for (int i = 0; i < n; ++i) {
if (a[i] >= step) {
sorted_by_second[ptr++] = a[i] - step;
}
}
for (int i = n - 1; ~i; --i) {
ptr_group[group[a[i]]] = i;
}
for (int i = 0; i < n; ++i) {
int x = sorted_by_second[i];
a[ptr_group[group[x]]++] = x;
}
new_group[a[0]] = 0;
for (int i = 1; i < n; ++i) {
if (group[a[i]] != group[a[i - 1]]) {
new_group[a[i]] = new_group[a[i - 1]] + 1;
} else {
int prev = a[i - 1] + step >= n ? -1 : group[a[i - 1] + step];
int now = a[i] + step >= n ? -1 : group[a[i] + step];
new_group[a[i]] = new_group[a[i - 1]] + (prev != now);
}
}
group = new_group;
step <<= 1;
}
return a;
}
template<typename T>
vector<int> build_lcp(const T &s, int n, const vector<int> &sa) {
vector<int> pos(n);
for (int i = 0; i < n; ++i) {
pos[sa[i]] = i;
}
vector<int> lcp(n - 1);
for (int i = 0, k = 0; i < n; ++i) {
k = max(k - 1, 0);
if (pos[i] == n - 1) {
k = 0;
} else {
int j = sa[pos[i] + 1];
while (i + k < n && j + k < n && s[i + k] == s[j + k]) {
++k;
}
lcp[pos[i]] = k;
}
}
return lcp;
}
class dsu {
public:
vector<int> p;
int n;
dsu(int n): n(n) {
p.resize(n);
for (int i = 0; i < n; ++i) {
p[i] = i;
}
}
inline int find(int x) {
while (x != p[x]) {
x = p[x] = p[p[x]];
}
return x;
}
inline bool unite(int x, int y) {
x = find(x);
y = find(y);
if (x == y) {
return false;
} else {
p[x] = y;
return true;
}
}
};
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
cout.setf(ios::fixed);
cout.precision(10);
int tt;
cin >> tt;
while (tt--) {
string s;
cin >> s;
int n = s.size();
vector<int> sa = suffix_array(s, n, 256);
vector<int> lcp = build_lcp(s, n, sa);
dsu p(n);
vector<double> ans(n);
for (int i = 0; i < n; ++i) {
ans[i] = n - sa[i];
}
vector<vector<int>> events(n);
for (int i = 0; i < n - 1; ++i) {
events[lcp[i]].push_back(i);
}
for (int i = n - 1; ~i; --i) {
for (auto j : events[i]) {
int k = p.find(j + 1);
double prob = (ans[k] - i) / (ans[j] + ans[k] - i * 2);
ans[k] = prob * ans[j] + (1 - prob) * i;
p.unite(j, k);
}
}
cout << ans[n - 1] << "\n";
}
return 0;
}
写个暴力就过了,可以证明复杂度正确。
#include
using namespace std;
class node {
public:
int minv = 0;
int maxv = 0;
int cover = 0;
long long sum = 0;
inline void apply(int l, int r, int v) {
minv = maxv = cover = v;
sum = (long long) (r - l + 1) * v;
}
};
class segtree {
public:
vector<node> tree;
int n;
inline node unite(const node &l, const node &r) {
node res;
res.minv = min(l.minv, r.minv);
res.maxv = max(l.maxv, r.maxv);
res.sum = l.sum + r.sum;
return res;
}
segtree(int n): n(n) {
tree.resize(n * 2 - 1);
}
inline void pull(int x, int z) {
tree[x] = unite(tree[x + 1], tree[z]);
}
inline void push(int x, int l, int r) {
int y = l + r >> 1, z = x + (y - l + 1 << 1);
if (tree[x].cover) {
tree[x + 1].apply(l, y, tree[x].cover);
tree[z].apply(y + 1, r, tree[x].cover);
tree[x].cover = 0;
}
}
void build(int x, int l, int r) {
if (l == r) {
tree[x].apply(l, r, n);
} else {
int y = l + r >> 1, z = x + (y - l + 1 << 1);
build(x + 1, l, y);
build(z, y + 1, r);
pull(x, z);
}
}
void reset(int x, int l, int r) {
if (tree[x].minv == tree[x].maxv) {
if (tree[x].minv != n) {
tree[x].apply(l, r, query(tree[x].minv, tree[x].minv).minv);
}
} else {
int y = l + r >> 1, z = x + (y - l + 1 << 1);
push(x, l, r);
reset(x + 1, l, y);
reset(z, y + 1, r);
pull(x, z);
}
}
int find_last(int x, int l, int r, int v) {
if (tree[x].maxv <= v) {
return r;
} else if (tree[x].minv > v) {
return -1;
} else {
int y = l + r >> 1, z = x + (y - l + 1 << 1);
push(x, l, r);
if (tree[z].minv <= v) {
return find_last(z, y + 1, r, v);
} else {
return find_last(x + 1, l, y, v);
}
}
}
template<typename... T>
void modify(int x, int l, int r, int ll, int rr, const T&... v) {
if (ll <= l && r <= rr) {
tree[x].apply(l, r, v...);
} else {
int y = l + r >> 1, z = x + (y - l + 1 << 1);
push(x, l, r);
if (ll <= y) {
modify(x + 1, l, y, ll, rr, v...);
}
if (rr > y) {
modify(z, y + 1, r, ll, rr, v...);
}
pull(x, z);
}
}
node query(int x, int l, int r, int ll, int rr) {
if (ll <= l && r <= rr) {
return tree[x];
} else {
int y = l + r >> 1, z = x + (y - l + 1 << 1);
push(x, l, r);
if (rr <= y) {
return query(x + 1, l, y, ll, rr);
} else if (ll > y) {
return query(z, y + 1, r, ll, rr);
} else {
return unite(query(x + 1, l, y, ll, rr), query(z, y + 1, r, ll, rr));
}
}
}
void build() {
build(0, 0, n - 1);
}
void reset() {
reset(0, 0, n - 1);
}
int find_last(int v) {
return find_last(0, 0, n - 1, v);
}
template<typename... T>
void modify(int l, int r, const T&... v) {
modify(0, 0, n - 1, l, r, v...);
}
node query(int l, int r) {
return query(0, 0, n - 1, l, r);
}
};
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m, q;
cin >> n >> m >> q;
vector<int> a(n);
vector<vector<int>> modifies(m);
for (int i = 0; i < n; ++i) {
cin >> a[i];
--a[i];
modifies[a[i]].push_back(i);
}
vector<int> l(q), r(q);
vector<vector<int>> queries(m);
for (int i = 0; i < q; ++i) {
int w;
cin >> l[i] >> r[i] >> w;
--l[i];
--r[i];
--w;
queries[w].push_back(i);
}
++n;
segtree seg(n);
seg.build();
vector<long long> ans(q);
for (int i = 0; i < m; ++i) {
seg.reset();
for (auto j : modifies[i]) {
int p = seg.find_last(j + 1);
if (p + 1 <= j) {
seg.modify(p + 1, j, j + 1);
}
}
for (auto j : queries[i]) {
int p = seg.find_last(r[j] + 1);
if (p >= l[j]) {
ans[j] = (long long) (p - l[j] + 1) * (r[j] + 2) - seg.query(l[j], p).sum;
}
}
}
for (int i = 0; i < q; ++i) {
cout << ans[i] << "\n";
}
return 0;
}
随便讨论一下。
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
vector<int> a(n);
vector<int> c(2);
for (int i = 0; i < n; ++i) {
cin >> a[i];
++c[a[i]];
}
vector<int> deg(n);
for (int i = 0; i < m; ++i) {
int from, to;
cin >> from >> to;
--from;
--to;
if (a[from] != a[to]) {
++deg[from];
++deg[to];
}
}
vector<int> d(2);
for (int i = 0; i < n; ++i) {
if (deg[i]) {
++d[a[i]];
}
}
for (int i = 0; i < n; ++i) {
int ans = 0;
if (!deg[i]) {
ans += c[a[i]] - 1;
ans += 2 * d[!a[i]];
ans += 3 * (c[!a[i]] - d[!a[i]]);
} else {
ans += c[a[i]] - 1;
ans += deg[i];
ans += 2 * (c[!a[i]] - deg[i]);
}
if (i) {
cout << " ";
}
cout << ans;
}
cout << "\n";
return 0;
}