终点 究竟有多远
那丧钟 倒数着轮回
我等待 人生的终结
却又不舍 这个世间
易得周期为 B ⋅ A gcd ( A , B + 1 ) B \cdot \frac{A}{\gcd(A,B+1)} B⋅gcd(A,B+1)A,排序离散化即可。 Θ ( n log n ) \Theta(n\log n) Θ(nlogn)
#include
#include
using namespace std;
typedef long long ll;
const int N = 1000010;
int n;
ll a, b, period;
pair<ll, int> modi[N * 2];
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
int main() {
scanf("%d%lld%lld", &n, &a, &b);
ll v = a / gcd(a, b + 1);
if (3e18 / v < b) period = 3e18;
else period = v * b;
for (int i = 1; i <= n; ++i) {
ll l, r;
scanf("%lld%lld", &l, &r);
if (++r - l >= period) {
printf("%lld\n", period);
return 0;
}
l %= period; r %= period;
if (l < r) {
modi[i * 2 - 1] = make_pair(l, 1);
modi[i * 2] = make_pair(r, -1);
} else {
modi[i * 2 - 1] = make_pair(l, 1);
modi[i * 2] = make_pair(r, -1);
++modi[0].second;
}
}
modi[n * 2 + 1].first = period;
sort(modi + 1, modi + n * 2 + 1);
ll ans = 0;
int cnt = 0;
for (int i = 0; i <= n * 2; ++i)
ans += bool(cnt += modi[i].second) * (modi[i + 1].first - modi[i].first);
printf("%lld\n", ans);
return 0;
}
按时间分块。这样每次都是一个缩小的图上考察连通性。 Θ ( q n log n ) \Theta(q \sqrt{n\log n}) Θ(qnlogn)
#include
#include
#include
#include
#include
#include
#define LOG(FMT...) fprintf(stderr, FMT)
using namespace std;
struct Node {
int u, v, w;
Node() : u(), v(), w() {}
Node(int u, int v, int w) : u(u), v(v), w(w) {}
bool operator>(const Node& rhs) const { return w > rhs.w; }
};
struct E {
int v;
E* next;
};
const int N = 50010, M = 100010, B = 3100;
int n, m, q;
Node e[M];
bool tag[M], vis[M];
int opt[M], x[M], y[M], ans[M];
pair<int, int> ed[M * 2];
int f[N], sz[N];
int req[B];
E pool[B * 2], *g[N];
E* ptop;
void adde(int u, int v) {
E* p = ptop++;
p->v = v;
p->next = g[u];
g[u] = p;
}
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
int dfs(int u) {
vis[u] = true;
int ret = sz[u];
for (E* p = g[u]; p; p = p->next)
if (!vis[p->v])
ret += dfs(p->v);
return ret;
}
int main() {
#ifdef LBT
freopen("test.in", "r", stdin);
int nol_cl = clock();
#endif
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++i)
scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
scanf("%d", &q);
for (int i = 1; i <= q; ++i)
scanf("%d%d%d", &opt[i], &x[i], &y[i]);
int b = sqrt(n * log2(n));
if (b < 1) b = 1;
for (int l = 1; l <= q; l += b) {
int r = min(q, l + b - 1);
int edc = 0, rc = 0;
memset(tag, 0, sizeof(tag));
for (int i = l; i <= r; ++i)
if (opt[i] == 1)
tag[x[i]] = true;
else
ed[++edc] = make_pair(y[i], -i);
for (int i = 1; i <= m; ++i)
if (!tag[i])
ed[++edc] = make_pair(e[i].w, i);
else
req[++rc] = i;
sort(ed + 1, ed + edc + 1, greater<pair<int, int> >());
iota(f + 1, f + n + 1, 1);
fill(sz + 1, sz + n + 1, 1);
for (int i = 1; i <= edc; ++i) {
if (ed[i].second > 0) {
int u = find(e[ed[i].second].u), v = find(e[ed[i].second].v);
if (u != v) {
sz[u] += sz[v];
f[v] = u;
}
} else {
ptop = pool;
for (int j = -ed[i].second; j >= l; --j) {
if (opt[j] == 1 && !vis[x[j]]) {
vis[x[j]] = true;
if (y[j] >= ed[i].first) {
int u = find(e[x[j]].u), v = find(e[x[j]].v);
adde(u, v);
adde(v, u);
}
}
}
for (int j = 1; j <= rc; ++j)
if (!vis[req[j]]) {
if (e[req[j]].w >= ed[i].first) {
int u = find(e[req[j]].u), v = find(e[req[j]].v);
adde(u, v);
adde(v, u);
}
} else
vis[req[j]] = false;
ans[-ed[i].second] = dfs(find(x[-ed[i].second]));
for (int j = 1; j <= rc; ++j) {
int u = find(e[req[j]].u), v = find(e[req[j]].v);
g[u] = g[v] = NULL;
vis[u] = vis[v] = false;
}
vis[find(x[-ed[i].second])] = false;
}
}
for (int i = l; i <= r; ++i)
if (opt[i] == 1)
e[x[i]].w = y[i];
}
for (int i = 1; i <= q; ++i)
if (ans[i])
printf("%d\n", ans[i]);
#ifdef LBT
LOG("Time: %dms\n", int ((clock()
-nol_cl) / (double)CLOCKS_PER_SEC * 1000));
#endif
return 0;
}
按道路从左至右扫描线,维护一个类单调栈状物,转三维偏序。 Θ ( n log 2 n ) \Theta(n\log^2 n) Θ(nlog2n)。
#include
#include
#include
#include
#define LOG(FMT...)
using namespace std;
struct Node {
int x, y, v;
Node() : x(), y(), v() {}
Node(int x, int y, int v) : x(x), y(y), v(v) {}
bool operator<(const Node& rhs) const {
if (x != rhs.x) return x < rhs.x;
return y < rhs.y;
}
};
const int N = 300010;
int n, q, fwn, cnt;
char s[N];
int state[N], fw[N], ans[N];
map<int, pair<int, int> > sg;
bool isQry[N];
vector<pair<int, int> > seg[N], qq[N];
Node seq[N * 8];
int lowBit(int k) { return k & -k; }
void ch(int k, int x) {
for (; k <= fwn; k += lowBit(k))
fw[k] += x;
}
int qry(int k) {
int ret = 0;
for (; k; k -= lowBit(k))
ret += fw[k];
return ret;
}
void dc(int l, int r) {
if (l == r) return;
int mid = l + ((r - l) >> 1);
dc(l, mid); dc(mid + 1, r);
int pt = mid + 1;
for (int i = l; i <= mid; ++i) {
while (pt <= r && seq[pt] < seq[i]) {
if (seq[pt].v >= N) {
ans[seq[pt].v - N] += qry(seq[pt].y);
}
++pt;
}
if (seq[i].v < N)
ch(seq[i].y, seq[i].v);
}
while (pt <= r) {
if (seq[pt].v >= N) {
ans[seq[pt].v - N] += qry(seq[pt].y);
}
++pt;
}
for (int i = l; i <= mid; ++i)
if (seq[i].v < N)
ch(seq[i].y, -seq[i].v);
inplace_merge(seq + l, seq + mid + 1, seq + r + 1);
}
void cut(int p) {
if (p == 0 || p == q) return;
map<int, pair<int, int>>::iterator it = sg.lower_bound(p);
if (it->first == p) return;
int l, x, r = it->first;
tie(l, x) = it->second;
seq[++cnt] = Node(x, r, -p + l - 1);
seq[++cnt] = Node(x, p, p - l + 1);
it->second.first = p + 1;
sg.insert(make_pair(p, make_pair(l, x)));
}
int main() {
scanf("%d%d%s", &n, &q, s + 1);
fwn = q;
for (int i = 1; i <= n; ++i)
state[i] = s[i] == '0';
for (int i = 1; i <= q; ++i) {
int x;
scanf("%s%d", s, &x);
if (s[0] == 't') {
if (state[x]) {
seg[x].push_back(make_pair(state[x], i));
state[x] = 0;
} else
state[x] = i + 1;
} else {
int y;
scanf("%d", &y);
qq[y - 1].push_back(make_pair(i, x));
isQry[i] = true;
}
}
for (int i = 1; i <= n; ++i)
if (state[i] && state[i] <= q)
seg[i].push_back(make_pair(state[i], q));
sg.insert(make_pair(q, make_pair(1, 1)));
seq[++cnt] = Node(1, q, q);
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < seg[i].size(); ++j) {
int l, r;
tie(l, r) = seg[i][j];
cut(l - 1);
cut(r);
for (auto it = sg.lower_bound(l); it != sg.end() && it->first <= r; sg.erase(it++))
seq[++cnt] = Node(it->second.second, it->first, -(it->first - it->second.first + 1));
seq[++cnt] = Node(i + 1, r, r - l + 1);
sg.insert(make_pair(r, make_pair(l, i + 1)));
}
for (const auto& qr : qq[i]) {
auto it = sg.lower_bound(qr.first);
if (it->second.second <= qr.second) {
ans[qr.first] += qr.first - it->second.first + 1;
}
if (it != sg.begin()) {
--it;
seq[++cnt] = Node(qr.second, it->first, qr.first + N);
}
}
}
dc(1, cnt);
for (int i = 1; i <= q; ++i)
if (isQry[i])
printf("%d\n", ans[i]);
return 0;
}