pyyz集训day7
https://files.cnblogs.com/files/blogs/832279/8.13数据结构选讲.zip?t=1786581382&download=true
献上代码:
1.Segment Tree Practice 4
点击查看代码
#include <iostream>
#include <vector>
#define lowbit(x) x & (-x)
using std::cin;
using std::cout;
const int N = 2e5 + 10;
struct Q
{
int l, r, k, id;
};
int n, q;
int a[N];
int ans[N];
int sum[N];
std::vector<int> pos[N];
std::vector<Q> ope[N];
void add(int x, int k)
{
for (; x <= n; x += lowbit(x))
sum[x] += k;
}
int query(int x)
{
int ret = 0;
for (; x; x -= lowbit(x))
ret += sum[x];
return ret;
}
int main()
{
cin >> n >> q;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
if (!pos[a[i]].size())
pos[a[i]].push_back(0);
pos[a[i]].push_back(i);
}
for (int i = 1; i <= n; ++i)
{
if (pos[i].size())
pos[i].push_back(n + 1);
}
for (int i = 1; i <= n; ++i)
{
if (!pos[i].size())
continue;
for (int j = 1; j <= (int)pos[i].size() - 2; ++j)
{
int l = pos[i][j - 1] + 1;
int r = pos[i][j + 1] - 1;
int m = pos[i][j];
ope[l].push_back({m, r, 1, 0});
if (m < n)
ope[m + 1].push_back({m, r, -1, 0});
}
}
for (int i = 1; i <= q; ++i)
{
int l, r;
cin >> l >> r;
ope[l].push_back({r, 0, 0, i});
}
for (int i = 1; i <= n; ++i)
{
for (auto it : ope[i])
{
if (it.id)
ans[it.id] = query(it.l);
else
{
add(it.l, it.k);
if (it.r < n)
add(it.r + 1, -it.k);
}
}
}
for (int i = 1; i <= q; ++i)
cout << ans[i] << '\n';
return 0;
}
2.k-d-sequence
点击查看代码
#include <iostream>
#include <map>
using std::cin;
using std::cout;
const int N = 2e5 + 10;
typedef long long ll;
const ll oo = 1e18;
struct Node
{
ll mn;
ll tag;
Node()
{
tag = 0;
mn = oo;
}
friend Node operator+(const Node &l, const Node &r)
{
Node ret;
ret.mn = std::min(l.mn, r.mn);
return ret;
}
} z[N << 2];
int top;
int top1;
int n, k, d;
int a[N];
int q[N];
int p[N];
int pre[N];
int stv[N];
int stl[N];
int str[N];
int stv1[N];
int stl1[N];
int str1[N];
std::map<int, int> pos;
#define root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
void add(int rt, ll v)
{
z[rt].mn += v;
z[rt].tag += v;
}
void push_down(int rt)
{
if (z[rt].tag)
{
add(rt << 1, z[rt].tag);
add(rt << 1 | 1, z[rt].tag);
z[rt].tag = 0;
}
}
void modiadd(int l, int r, int rt, int nowl, int nowr, ll v)
{
if (nowl <= l && r <= nowr)
{
add(rt, v);
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if (nowl <= mid)
modiadd(lson, nowl, nowr, v);
if (nowr > mid)
modiadd(rson, nowl, nowr, v);
z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
int query(int l, int r, int rt, int nowl, int nowr, ll k)
{
if (nowl > nowr)
return -1;
if (nowl <= l && r <= nowr)
{
if (z[rt].mn > k)
return -1;
if (l == r)
return l;
int mid = (l + r) >> 1;
push_down(rt);
if (z[rt << 1].mn <= k)
return query(lson, nowl, nowr, k);
else
return query(rson, nowl, nowr, k);
}
push_down(rt);
int mid = (l + r) >> 1;
int ans = -1;
if (nowl <= mid)
ans = query(lson, nowl, nowr, k);
if (ans == -1 && nowr > mid)
ans = query(rson, nowl, nowr, k);
return ans;
}
void build(int l, int r, int rt)
{
if (l == r)
{
z[rt].mn = l - k;
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
Node qdebug(int l, int r, int rt, int nowl, int nowr)
{
if (nowl <= l && r <= nowr)
return z[rt];
int mid = (l + r) >> 1;
push_down(rt);
if (nowl <= mid)
{
if (nowr > mid)
return qdebug(lson, nowl, nowr) + qdebug(rson, nowl, nowr);
else
return qdebug(lson, nowl, nowr);
}
else
return qdebug(rson, nowl, nowr);
}
int main()
{
cin >> n >> k >> d;
for (int i = 1; i <= n; ++i)
cin >> a[i];
if (!d)
{
int ans = 0;
int al, ar;
for (int i = 1; i <= n; ++i)
{
int j = i - 1;
while (j < n && a[j + 1] == a[i])
j++;
if (ans < j - i + 1)
{
ans = j - i + 1;
al = i, ar = j;
}
i = j;
}
cout << al << ' ' << ar << '\n';
return 0;
}
for (int i = 1; i <= n; ++i)
q[i] = (a[i] % d + d) % d, p[i] = (a[i] - q[i]) / d;
for (int i = 1; i <= n; ++i)
{
pre[i] = pos[a[i]];
pos[a[i]] = i;
}
build(root);
int ans = 0;
int al, ar;
for (int i = 1; i <= n; ++i)
{
int nl = i, nr = i - 1;
while (nr < n && q[nr + 1] == q[nl])
nr++;
int ql = nl;
top = 0, top1 = 0;
for (int j = nl; j <= nr; ++j)
{
modiadd(root, nl, nr, (j == nl ? -j : (j - 1) - j));
while (top && stv[top] <= p[j])
{
modiadd(root, stl[top], str[top], -stv[top]);
top--;
}
++top;
stv[top] = p[j];
stl[top] = str[top - 1] + 1;
str[top] = j;
modiadd(root, stl[top], str[top], stv[top]);
while (top1 && stv1[top1] >= p[j])
{
modiadd(root, stl1[top1], str1[top1], stv1[top1]);
top1--;
}
++top1;
stv1[top1] = p[j];
stl1[top1] = str1[top1 - 1] + 1;
str1[top1] = j;
modiadd(root, stl1[top1], str1[top1], -stv1[top1]);
ql = std::max(ql, pre[j] + 1);
int now = query(root, ql, j, 0);
if (now != -1)
{
if (ans < j - now + 1)
{
ans = j - now + 1;
al = now, ar = j;
}
}
}
i = nr;
}
cout << al << ' ' << ar << '\n';
return 0;
}
3.A. 数据结构
点击查看代码
#include <iostream>
#include <vector>
#define lowbit(x) x & (-x)
using std::cin;
using std::cout;
const int N = 1e6 + 10;
struct Node
{
int l, r;
int k;
int id;
};
int n, m;
int l[N];
int r[N];
int a[N];
int ans[N];
int sum[N];
int cnt[N];
std::vector<int> num;
std::vector<int> pos[N];
std::vector<Node> ope[N];
void add(int x, int k)
{
for (; x <= n; x += lowbit(x))
sum[x] += k;
}
int query(int x)
{
int ret = 0;
for (; x; x -= lowbit(x))
ret += sum[x];
return ret;
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
cnt[a[i]]++;
if (cnt[a[i]] == 1)
pos[a[i]].push_back(0);
pos[a[i]].push_back(i);
if (!l[a[i]])
l[a[i]] = i;
r[a[i]] = i;
}
for (int i = 1; i <= n; ++i)
{
if (cnt[i])
{
pos[i].push_back(n + 1);
num.push_back(i);
if (!cnt[i + 1])
num.push_back(i + 1);
}
}
for (auto it : num)
{
if (!cnt[it])
{
for (int i = 1; i < (int)pos[it - 1].size(); ++i)
{
int x = pos[it - 1][i - 1] + 1;
int y = pos[it - 1][i] - 1;
if (x <= y)
{
ope[x].push_back({x, y, 1, 0});
if (y < n)
ope[y + 1].push_back({x, y, -1, 0});
}
}
}
else if (!cnt[it - 1])
{
int x = l[it];
int y = r[it];
if (x >= 1 && y <= n)
{
ope[1].push_back({y, n, 1, 0});
if (x < n)
ope[x + 1].push_back({y, n, -1, 0});
}
}
else
{
int x = l[it];
int y = r[it];
for (int i = 1; i < (int)pos[it - 1].size(); ++i)
{
int a = pos[it - 1][i - 1] + 1;
int b = pos[it - 1][i] - 1;
if (a <= x && y <= b)
{
ope[a].push_back({y, b, 1, 0});
if (x < n)
ope[x + 1].push_back({y, b, -1, 0});
}
}
}
}
for (int i = 1; i <= m; ++i)
{
int l, r;
cin >> l >> r;
ope[l].push_back({r, 0, 0, i});
}
for (int i = 1; i <= n; ++i)
{
for (auto it : ope[i])
{
if (it.id)
ans[it.id] = query(it.l);
else
{
add(it.l, it.k);
if (it.r < n)
add(it.r + 1, -it.k);
}
}
}
for (int i = 1; i <= m; ++i)
cout << num.size() - ans[i] << '\n';
return 0;
}
4.rldcot
点击查看代码
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
#define pii std::pair<int, int>
#define lowbit(x) x & (-x)
using std::cin;
using std::cout;
const int N = 1e5 + 10;
typedef long long ll;
struct Mod
{
int l, r, id;
bool q;
};
int n, m;
int top;
int id[N];
int sum[N];
int ans[N * 5];
pii stk[N];
ll dist[N];
std::vector<ll> vec;
std::set<int> s[N];
std::vector<pii> e[N];
std::vector<pii> pr[N];
std::vector<Mod> modi[N];
void dfs(int x, int fa)
{
for (auto nxt : e[x])
{
int to = nxt.first;
if (to == fa)
continue;
int val = nxt.second;
dist[to] = dist[x] + val;
dfs(to, x);
}
}
void dfs2(int x, int fa)
{
for (auto nxt : e[x])
{
int to = nxt.first;
if (to != fa)
dfs2(to, x);
}
s[x].insert(x);
pr[dist[x]].push_back({x, x});
id[x] = x;
for (auto nxt : e[x])
{
int to = nxt.first;
if (to != fa)
{
if (s[id[x]].size() < s[id[to]].size())
std::swap(id[x], id[to]);
for (auto it : s[id[to]])
{
auto a = s[id[x]].lower_bound(it);
if (a != s[id[x]].end())
pr[dist[x]].push_back({std::min(it, *a), std::max(it, *a)});
if (a != s[id[x]].begin())
{
auto b = std::prev(a);
pr[dist[x]].push_back({std::min(it, *b), std::max(it, *b)});
}
}
for (auto it : s[id[to]])
s[id[x]].insert(it);
}
}
}
void add(int x, int k)
{
for (; x <= n; x += lowbit(x))
sum[x] += k;
}
int query(int x)
{
int ret = 0;
for (; x; x -= lowbit(x))
ret += sum[x];
return ret;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
for (int i = 1; i < n; ++i)
{
int u, v, d;
cin >> u >> v >> d;
e[u].push_back({v, d});
e[v].push_back({u, d});
}
dfs(1, 0);
for (int i = 1; i <= n; ++i)
vec.push_back(dist[i]);
std::sort(vec.begin(), vec.end());
vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
int tot = vec.size();
for (int i = 1; i <= n; ++i)
dist[i] = std::lower_bound(vec.begin(), vec.end(), dist[i]) - vec.begin() + 1;
dfs2(1, 0);
for (int i = 1; i <= tot; ++i)
{
std::sort(pr[i].begin(), pr[i].end());
int top = 0;
for (auto it : pr[i])
{
int x = it.first;
int y = it.second;
if (top && stk[top].first == x)
continue;
while (top && stk[top].second >= y)
top--;
stk[++top] = it;
}
stk[0] = {0, 0};
for (int i = 1; i <= top; ++i)
modi[stk[i].second].push_back({stk[i - 1].first + 1, stk[i].first, 0, false});
}
for (int i = 1; i <= m; ++i)
{
int l, r;
cin >> l >> r;
modi[r].push_back({l, 0, i, true});
}
for (int i = 1; i <= n; ++i)
{
for (auto it : modi[i])
{
if (!it.q)
{
add(it.l, 1);
if (it.r < n)
add(it.r + 1, -1);
}
else
ans[it.id] = query(it.l);
}
}
for (int i = 1; i <= m; ++i)
cout << ans[i] << '\n';
return 0;
}
ps:这道题卡线段树,请用树状数组。
5.フードコート (Day1)
点击查看代码
#include <iostream>
#include <vector>
#define int long long
using std::cin;
using std::cout;
const int N = 2.5e5 + 10;
struct Mod
{
int t, v, c;
int q;
};
struct Node
{
int sum1;
int id;
int sum2;
int min;
int p;
friend Node operator+(const Node &l, const Node &r)
{
Node ret;
ret.sum1 = l.sum1 + r.sum1;
ret.sum2 = l.sum2 + r.sum2;
if (l.min <= l.sum2 + r.min)
ret.min = l.min, ret.p = l.p;
else
ret.min = l.sum2 + r.min, ret.p = r.p;
return ret;
}
} z[N << 2];
int S;
bool qr[N];
int ans[N];
std::vector<Mod> mod[N];
#define root 1, q, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
void modicov(int l, int r, int rt, int p, int id, int k)
{
if (l == r)
{
if (k >= 0)
z[rt].sum1 = k;
else
z[rt].sum1 = 0;
z[rt].sum2 = z[rt].min = k;
z[rt].id = id;
z[rt].p = l;
return;
}
int mid = (l + r) >> 1;
if (p <= mid)
modicov(lson, p, id, k);
else
modicov(rson, p, id, k);
z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
Node query(int l, int r, int rt, int nowl, int nowr)
{
if (nowl <= l && r <= nowr)
return z[rt];
int mid = (l + r) >> 1;
if (nowl <= mid)
{
if (nowr > mid)
return query(lson, nowl, nowr) + query(rson, nowl, nowr);
else
return query(lson, nowl, nowr);
}
else
return query(rson, nowl, nowr);
}
int qp(int l, int r, int rt, int nowl, int nowr, int k)
{
if (nowl <= l && r <= nowr)
{
if (z[rt].sum1 + S < k)
return S += z[rt].sum1, -1;
if (l == r)
return z[rt].id;
int mid = (l + r) >> 1;
if (S + z[rt << 1 | 1].sum1 >= k)
return qp(rson, nowl, nowr, k);
else
return S += z[rt << 1 | 1].sum1, qp(lson, nowl, nowr, k);
}
int mid = (l + r) >> 1;
int ans = -1;
if (nowr > mid)
ans = qp(rson, nowl, nowr, k);
if (ans == -1 && nowl <= mid)
ans = qp(lson, nowl, nowr, k);
return ans;
}
signed main()
{
int n, m, q;
cin >> n >> m >> q;
for (int i = 1; i <= q; ++i)
{
int t;
cin >> t;
if (t == 1)
{
int l, r, c, k;
cin >> l >> r >> c >> k;
mod[l].push_back({i, c, k, 0});
if (r < n)
mod[r + 1].push_back({i, 0, 0, 1});
}
else if (t == 2)
{
int l, r, k;
cin >> l >> r >> k;
mod[l].push_back({i, 0, -k, 2});
if (r < n)
mod[r + 1].push_back({i, 0, 0, 3});
}
else
{
qr[i] = true;
int a, b;
cin >> a >> b;
mod[a].push_back({i, 0, b, 4});
}
}
for (int i = 1; i <= n; ++i)
{
for (auto it : mod[i])
{
if (it.q <= 3)
modicov(root, it.t, it.v, it.c);
else
{
S = 0;
int mnp = query(root, 1, it.t).p;
int beg;
if (mnp == 0 || query(root, 1, mnp).sum2 >= 0)
beg = 1;
else
beg = mnp + 1;
int sm = query(root, beg, it.t).sum2;
if (sm < it.c)
ans[it.t] = 0;
else
ans[it.t] = qp(root, beg, it.t, sm - it.c + 1);
}
}
}
for (int i = 1; i <= q; ++i)
{
if (qr[i])
cout << ans[i] << '\n';
}
return 0;
}
6.火车管理
点击查看代码
#include <iostream>
using std::cin;
using std::cout;
const int N = 5e5 + 10;
struct Node
{
int l, r;
int sum;
int id;
short tag;
Node()
{
l = r = sum = 0;
tag = -1;
id = -1;
}
} z[N * 80];
bool tag = 0;
int tot;
int mid;
int root[N];
inline void add(const int &rt, const int &l, const int &r, const short &k)
{
z[rt].sum = (r - l + 1) * k;
z[rt].tag = k;
}
inline void cov(const int &rt, const int &id)
{
z[rt].id = id;
}
inline void push_down(const int &rt, const int &l, const int &r)
{
if (z[rt].id != -1 || z[rt].tag != -1)
{
mid = (l + r) >> 1;
++tot;
z[tot] = z[z[rt].l];
if (l == mid && z[tot].id == -1)
z[tot].id = 0;
z[rt].l = tot;
++tot;
z[tot] = z[z[rt].r];
if (mid + 1 == r && z[tot].id == -1)
z[tot].id = 0;
z[rt].r = tot;
if (z[rt].tag != -1)
{
add(z[rt].l, l, mid, z[rt].tag);
add(z[rt].r, mid + 1, r, z[rt].tag);
z[rt].tag = -1;
}
if (z[rt].id != -1)
{
cov(z[rt].l, z[rt].id);
cov(z[rt].r, z[rt].id);
z[rt].id = -1;
}
tag = true;
}
}
inline void push_up(const int &rt)
{
z[rt].sum = z[z[rt].l].sum + z[z[rt].r].sum;
}
inline int modify(const int &l, const int &r, int rt, const int &nowl, const int &nowr, const int &id, const short &v, bool t)
{
if (!t)
{
++tot;
z[tot] = z[rt];
rt = tot;
if (l == r && z[rt].id == -1)
z[rt].id = 0;
}
if (nowl <= l && r <= nowr)
{
add(rt, l, r, v);
cov(rt, id);
return rt;
}
int mid = (l + r) >> 1;
tag = 0;
push_down(rt, l, r);
bool nw = tag;
if (nowl <= mid)
z[rt].l = modify(l, mid, z[rt].l, nowl, nowr, id, v, nw);
if (nowr > mid)
z[rt].r = modify(mid + 1, r, z[rt].r, nowl, nowr, id, v, nw);
push_up(rt);
return rt;
}
inline int qs(const int &l, const int &r, const int &rt, const int &nowl, const int &nowr)
{
if (!rt)
return 0;
if (z[rt].tag == 0)
return 0;
if (nowl <= l && r <= nowr)
return z[rt].sum;
int mid = (l + r) >> 1;
push_down(rt, l, r);
if (nowl <= mid)
{
if (nowr > mid)
return qs(l, mid, z[rt].l, nowl, nowr) + qs(mid + 1, r, z[rt].r, nowl, nowr);
else
return qs(l, mid, z[rt].l, nowl, nowr);
}
else
return qs(mid + 1, r, z[rt].r, nowl, nowr);
}
inline int qid(const int &l, const int &r, const int &rt, const int &p)
{
if (!rt)
return 0;
if (z[rt].id == 0)
return 0;
if (l == r)
return z[rt].id;
int mid = (l + r) >> 1;
push_down(rt, l, r);
if (p <= mid)
return qid(l, mid, z[rt].l, p);
else
return qid(mid + 1, r, z[rt].r, p);
}
inline int pointcov(const int &l, const int &r, int rt, const int &p, const short &k, const int &id)
{
++tot;
z[tot] = z[rt];
rt = tot;
if (l == r && z[rt].id == -1)
z[rt].id = 0;
if (l == r)
{
z[rt].id = id;
z[rt].sum = k;
return rt;
}
int mid = (l + r) >> 1;
push_down(rt, l, r);
if (p <= mid)
z[rt].l = pointcov(l, mid, z[rt].l, p, k, id);
else
z[rt].r = pointcov(mid + 1, r, z[rt].r, p, k, id);
push_up(rt);
return rt;
}
int main()
{
int l1, r1, l2, r2, l, r, opt, id;
short x;
int n, m, ty;
cin >> n >> m >> ty;
int lst = 0;
int idx = 0;
for (int i = 1; i <= m; ++i)
{
cin >> opt;
if (opt == 1)
{
cin >> l1 >> r1;
l2 = (1ll * l1 + lst * ty) % n + 1;
r2 = (1ll * r1 + lst * ty) % n + 1;
l = std::min(l2, r2);
r = std::max(l2, r2);
cout << (lst = qs(1, n, root[idx], l, r)) << '\n';
}
else if (opt == 2)
{
cin >> l1;
l = (1ll * l1 + lst * ty) % n + 1;
id = qid(1, n, root[idx], l);
if (!id)
continue;
++idx;
root[idx] = pointcov(1, n, root[idx - 1], l, qs(1, n, root[id - 1], l, l), qid(1, n, root[id - 1], l));
}
else if (opt == 3)
{
cin >> l1 >> r1 >> x;
l2 = (1ll * l1 + lst * ty) % n + 1;
r2 = (1ll * r1 + lst * ty) % n + 1;
l = std::min(l2, r2);
r = std::max(l2, r2);
++idx;
root[idx] = modify(1, n, root[idx - 1], l, r, idx, x, 0);
}
}
return 0;
}
ps:一次区间修改即使加上push_down,访问的总结点数也不超过 \(4\log_2 n\),如果push_down新建了节点,则访问到儿子的时候就不用新建节点了。
7.Souvenirs
点击查看代码
#include <iostream>
#include <algorithm>
#include <vector>
using std::cin;
using std::cout;
const int N = 1e5 + 10;
const int oo = 1e9 + 10;
struct Line
{
int l, r, k;
int q, id;
};
struct Node1
{
int mx;
int l, r;
Node1()
{
mx = 0;
}
friend Node1 operator+(const Node1 &a, const Node1 &b)
{
Node1 ret;
ret.mx = std::max(a.mx, b.mx);
return ret;
}
} z1[N * 31];
struct Node2
{
int mn;
int tag;
int l, r;
Node2()
{
mn = oo;
tag = oo;
}
} z2[N << 1];
int tot1, tot2;
int root1, root2;
int a[N];
int ans[(int)2e5 + 10];
int val[N];
std::vector<Line> modi[N];
void push_up1(int rt)
{
z1[rt].mx = std::max(z1[z1[rt].l].mx, z1[z1[rt].r].mx);
}
void push_up2(int rt)
{
z2[rt].mn = std::min(z2[z2[rt].l].mn, z2[z2[rt].r].mn);
}
void chm2(int rt, int k)
{
z2[rt].mn = std::min(z2[rt].mn, k);
z2[rt].tag = std::min(z2[rt].tag, k);
}
void push_down2(int rt)
{
if (z2[rt].tag != oo)
{
if (!z2[rt].l)
z2[rt].l = ++tot2;
chm2(z2[rt].l, z2[rt].tag);
if (!z2[rt].r)
z2[rt].r = ++tot2;
chm2(z2[rt].r, z2[rt].tag);
z2[rt].tag = oo;
}
}
void modichm1(int l, int r, int &rt, int p, int k)
{
if (!rt)
rt = ++tot1;
if (l == r)
{
z1[rt].mx = std::max(z1[rt].mx, k);
return;
}
int mid = (l + r) >> 1;
if (p <= mid)
modichm1(l, mid, z1[rt].l, p, k);
else
modichm1(mid + 1, r, z1[rt].r, p, k);
push_up1(rt);
}
void modichm2(int l, int r, int &rt, int nowl, int nowr, int k)
{
if (!rt)
rt = ++tot2;
if (nowl <= l && r <= nowr)
{
chm2(rt, k);
return;
}
push_down2(rt);
int mid = (l + r) >> 1;
if (nowl <= mid)
modichm2(l, mid, z2[rt].l, nowl, nowr, k);
if (nowr > mid)
modichm2(mid + 1, r, z2[rt].r, nowl, nowr, k);
push_up2(rt);
}
Node1 query1(int l, int r, int rt, int nowl, int nowr)
{
if (!rt)
return Node1();
if (nowl <= l && r <= nowr)
return z1[rt];
int mid = (l + r) >> 1;
if (nowl <= mid)
{
if (nowr > mid)
return query1(l, mid, z1[rt].l, nowl, nowr) + query1(mid + 1, r, z1[rt].r, nowl, nowr);
else
return query1(l, mid, z1[rt].l, nowl, nowr);
}
else
return query1(mid + 1, r, z1[rt].r, nowl, nowr);
}
int query2(int l, int r, int rt, int p)
{
if (l == r)
return z2[rt].mn;
int mid = (l + r) >> 1;
push_down2(rt);
if (p <= mid)
return query2(l, mid, z2[rt].l, p);
else
return query2(mid + 1, r, z2[rt].r, p);
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i];
modichm1(0, 1e9, root1, a[1], 1);
for (int i = 2; i <= n; ++i)
{
int now = query1(0, 1e9, root1, a[i], 1e9).mx;
if (now)
{
modi[i].push_back({1, now, a[now] - a[i], 0, 0});
while (true)
{
int now2 = query1(0, 1e9, root1, a[i], (a[now] + a[i]) >> 1).mx;
if (!now2 || now2 == now)
break;
now = now2;
modi[i].push_back({1, now, a[now] - a[i], 0, 0});
}
}
now = query1(0, 1e9, root1, 0, a[i]).mx;
if (now)
{
modi[i].push_back({1, now, a[i] - a[now]});
while (true)
{
int now2 = query1(0, 1e9, root1, (a[now] + a[i]) >> 1, a[i]).mx;
if (!now2 || now2 == now)
break;
now = now2;
modi[i].push_back({1, now, a[i] - a[now], 0, 0});
}
}
modichm1(0, 1e9, root1, a[i], i);
}
int m;
cin >> m;
for (int i = 1; i <= m; ++i)
{
int l, r;
cin >> l >> r;
modi[r].push_back({0, 0, l, 1, i});
}
for (int i = 1; i <= n; ++i)
{
for (Line it : modi[i])
{
if (!it.q)
modichm2(1, n, root2, it.l, it.r, it.k);
else
ans[it.id] = query2(1, n, root2, it.k);
}
}
for (int i = 1; i <= m; ++i)
cout << ans[i] << '\n';
return 0;
}
ps:ans数组一定要开2e5,不要开成N。
8.Sasha and Array
点击查看代码
#include <iostream>
using std::cin;
using std::cout;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
struct Mat
{
int n, m;
int a[3][3];
Mat()
{
a[1][1] = a[1][2] = a[2][1] = a[2][2] = 0;
}
void init(int x)
{
*this = Mat();
n = m = x;
for (int i = 1; i <= x; ++i)
a[i][i] = 1;
}
friend Mat operator+(const Mat &a, const Mat &b)
{
Mat ret;
ret.n = a.n, ret.m = a.m;
for (int i = 1; i <= a.n; ++i)
{
for (int j = 1; j <= a.m; ++j)
ret.a[i][j] = (a.a[i][j] + b.a[i][j]) % mod;
}
return ret;
}
friend Mat operator*(const Mat &a, const Mat &b)
{
Mat ret;
ret.n = a.n, ret.m = b.m;
for (int i = 1; i <= a.n; ++i)
{
for (int j = 1; j <= a.m; ++j)
{
for (int k = 1; k <= b.m; ++k)
ret.a[i][k] = (ret.a[i][k] + 1ll * a.a[i][j] * b.a[j][k] % mod) % mod;
}
}
return ret;
}
friend bool operator==(const Mat &a, const Mat &b)
{
if (a.n != b.n || a.m != b.m)
return false;
for (int i = 1; i <= a.n; ++i)
{
for (int j = 1; j <= a.m; ++j)
{
if ((a.a[i][j]) != (b.a[i][j]))
return false;
}
}
return true;
}
} I, k, c;
struct Node
{
Mat sum;
Mat tag;
Node()
{
tag = I;
}
friend Node operator+(const Node &l, const Node &r)
{
Node ret;
ret.sum = l.sum + r.sum;
return ret;
}
} z[N << 2];
int a[N];
#define root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
void mul(int rt, Mat mul)
{
z[rt].tag = mul * z[rt].tag;
z[rt].sum = mul * z[rt].sum;
}
void push_down(int rt)
{
if (!(z[rt].tag == I))
{
mul(rt << 1, z[rt].tag);
mul(rt << 1 | 1, z[rt].tag);
z[rt].tag = I;
}
}
Mat ksm(Mat a, int b)
{
Mat ret = I;
for (; b; a = a * a, b >>= 1)
{
if (b & 1)
ret = ret * a;
}
return ret;
}
void build(int l, int r, int rt)
{
if (l == r)
{
z[rt].sum = ksm(k, a[l]) * c;
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
void modify(int l, int r, int rt, int nowl, int nowr, Mat f)
{
if (nowl <= l && r <= nowr)
{
z[rt].sum = f * z[rt].sum;
z[rt].tag = f * z[rt].tag;
return;
}
push_down(rt);
int mid = (l + r) >> 1;
if (nowl <= mid)
modify(lson, nowl, nowr, f);
if (nowr > mid)
modify(rson, nowl, nowr, f);
z[rt] = z[rt << 1] + z[rt << 1 | 1];
}
Node query(int l, int r, int rt, int nowl, int nowr)
{
if (nowl <= l && r <= nowr)
return z[rt];
push_down(rt);
int mid = (l + r) >> 1;
if (nowl <= mid)
{
if (nowr > mid)
return query(lson, nowl, nowr) + query(rson, nowl, nowr);
else
return query(lson, nowl, nowr);
}
else
return query(rson, nowl, nowr);
}
int main()
{
I.init(2);
c.n = 2;
c.m = 1;
c.a[1][1] = 1;
k.n = k.m = 2;
k.a[1][1] = k.a[1][2] = k.a[2][1] = 1;
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> a[i];
build(root);
for (int i = 1; i <= m; ++i)
{
int opt;
cin >> opt;
if (opt == 1)
{
int l, r, x;
cin >> l >> r >> x;
modify(root, l, r, ksm(k, x));
}
else if (opt == 2)
{
int l, r;
cin >> l >> r;
cout << query(root, l, r).sum.a[2][1] << '\n';
}
}
return 0;
}
ps:modify不要在修改的时候再算ksm,一定要在传参的时候就把ksm出来的矩阵传进去。
9.楼房重建
点击查看代码
#include <iostream>
using std::cin;
using std::cout;
const int N = 1e5 + 10;
struct Node
{
int cnt;
int leaf;
int bian;
double maxv;
Node()
{
cnt = maxv = 0;
}
} z[N << 2];
#define root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
int query(int rt, double h)
{
if (z[rt].leaf)
return z[rt].maxv > h ? 1 : 0;
if (z[rt << 1].maxv > h)
{
int ret = z[rt].cnt - z[rt << 1].cnt;
ret += query(rt << 1, h);
return ret;
}
else
return query(rt << 1 | 1, h);
}
void push_up(int rt)
{
z[rt].maxv = std::max(z[rt << 1].maxv, z[rt << 1 | 1].maxv);
z[rt].cnt = z[rt << 1].cnt + query(rt << 1 | 1, z[rt << 1].maxv);
}
void build(int l, int r, int rt)
{
if (l == r)
{
z[rt].leaf = true;
z[rt].cnt = 1;
z[rt].bian = rt;
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
void modify(int l, int r, int rt, int p, double k)
{
if (l == r)
{
z[rt].cnt = 1;
z[rt].maxv = k;
return;
}
int mid = (l + r) >> 1;
if (p <= mid)
modify(lson, p, k);
else
modify(rson, p, k);
push_up(rt);
}
int main()
{
int n, m;
cin >> n >> m;
build(root);
for (int i = 1; i <= m; ++i)
{
int x, y;
cin >> x >> y;
modify(root, x, (double)y / x);
cout << query(1, 0) << '\n';
}
return 0;
}
10.Hungry Cow P
点击查看代码
#include <iostream>
using std::cin;
using std::cout;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
typedef __int128 ll;
struct Node
{
int sm;
ll l, r;
int ls, rs;
ll alr, rst;
} z[N * 60];
int tot;
int root;
ll inv2;
int query(int rt, ll k, ll l, ll r)
{
if (!rt)
return (k <= r - l + 1 ? (l + l + k - 1) % mod * k % mod * inv2 % mod : (l + r) % mod * (r - l + 1) % mod * inv2 % mod);
if (l == r)
return l % mod;
ll mid = (l + r) >> 1;
if (z[z[rt].ls].alr + k <= mid - l + 1)
return ((query(z[rt].ls, k, l, mid) + z[rt].sm - z[z[rt].ls].sm) % mod + mod) % mod;
else
return ((l + mid) % mod * (mid - l + 1) % mod * inv2 % mod + query(z[rt].rs, k - (mid - l + 1 - z[z[rt].ls].alr) + z[z[rt].ls].rst, mid + 1, r)) % mod;
}
void wrt(ll x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x >= 10)
wrt(x / 10);
putchar(x % 10 + '0');
}
void push_up(int rt)
{
ll l = z[rt].l, r = z[rt].r;
int ls = z[rt].ls, rs = z[rt].rs;
ll mid = (l + r) >> 1;
z[rt].rst = z[rs].rst + (z[ls].rst <= r - mid - z[rs].alr ? 0 : z[ls].rst - (r - mid - z[rs].alr));
z[rt].alr = z[ls].alr + (z[ls].rst <= r - mid - z[rs].alr ? z[ls].rst + z[rs].alr : r - mid);
if (z[ls].rst)
z[rt].sm = (z[ls].sm + query(rs, z[ls].rst, mid + 1, r)) % mod;
else
z[rt].sm = (z[ls].sm + z[rs].sm) % mod;
}
void modicov(ll l, ll r, int &rt, ll p, ll k)
{
if (!rt)
{
rt = ++tot;
z[rt].l = l, z[rt].r = r;
}
if (l == r)
{
if (k >= 1)
{
z[rt].sm = l % mod;
z[rt].alr = 1;
z[rt].rst = k - 1;
}
else
{
z[rt].sm = 0;
z[rt].alr = 0;
z[rt].rst = 0;
}
return;
}
ll mid = (l + r) >> 1;
if (p <= mid)
modicov(l, mid, z[rt].ls, p, k);
else
modicov(mid + 1, r, z[rt].rs, p, k);
push_up(rt);
}
int main()
{
inv2 = 5e8 + 4;
int u;
cin >> u;
while (u--)
{
long long d, b;
cin >> d >> b;
modicov(1, 1e23, root, d, b);
cout << z[root].sm << '\n';
}
return 0;
}
ps:这道题算的是所有能吃草的天的编号之和,而非天数。
11.Moniphant Sleep
点击查看代码
#include <iostream>
#include <cmath>
#include <set>
#define lowbit(x) x & (-x)
using std::cin;
using std::cout;
const int N = 5e5 + 10;
struct Node
{
int l, r;
mutable int v;
friend bool operator<(const Node &a, const Node &b)
{
return (a.l ^ b.l ? a.l < b.l : a.r < b.r);
}
};
int n, q;
std::set<Node> s;
int sum[N];
inline auto split(int x)
{
auto it = s.lower_bound({x, 0, 0});
if (it != s.end() && it->l == x)
return it;
it--;
int l = it->l, r = it->r, v = it->v;
s.erase(it);
s.insert({l, x - 1, v});
return s.insert({x, r, v}).first;
}
inline void cover(int l, int r, int v)
{
auto it2 = split(r + 1);
auto it1 = split(l);
s.erase(it1, it2);
s.insert({l, r, v});
}
inline void add(int x, int v)
{
for (; x <= n; x += lowbit(x))
sum[x] += v;
}
inline int query(int x)
{
int ret = 0;
for (; x; x -= lowbit(x))
ret += sum[x];
return ret;
}
inline void modiadd(int l, int r)
{
auto it2 = split(r + 1);
auto it1 = split(l);
for (auto i = it1; i != it2; ++i)
{
if (i->v != -1)
i->v++;
}
}
inline void modimin(int l, int r)
{
auto it2 = split(r + 1);
auto it1 = split(l);
for (auto i = it1; i != it2; ++i)
{
if (i->v != -1)
i->v--;
}
}
inline void modicov(int l, int r)
{
auto it2 = split(r + 1);
auto it1 = split(l);
for (auto i = it1; i != it2; ++i)
{
if (i->v == -1)
i->v = 0;
}
}
inline void perform(int l, int r)
{
auto it2 = split(r + 1);
auto it1 = split(l);
for (auto i = it1; i != it2; ++i)
{
if (i->v != -1)
{
if (i->v)
{
add(i->l, -i->v);
if (i->r < n)
add(i->r + 1, i->v);
}
i->v = -1;
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n >> q;
add(1, 5e5);
s.insert({1, n, -1});
int B = sqrt(n);
while (q--)
{
int opt, l, r;
cin >> opt >> l >> r;
if (opt == 1)
{
add(l, 1);
if (r < n)
add(r + 1, -1);
modiadd(l, r);
}
else if (opt == 2)
{
add(l, -1);
if (r < n)
add(r + 1, 1);
modimin(l, r);
}
else if (opt == 3)
modicov(l, r);
else if (opt == 4)
perform(l, r);
else if (opt == 5)
cout << query(l) << '\n';
if (s.size() > B)
{
auto it = s.begin();
while (true)
{
auto nxt = std::next(it);
if (nxt == s.end())
break;
if (it->v == nxt->v)
{
int l = it->l, r = nxt->r, v = it->v;
s.erase(it);
s.erase(nxt);
it = s.insert({l, r, v}).first;
}
else
it++;
}
}
}
return 0;
}
ps:ODT要先split(r + 1),再split(l),我这里设了一个阈值,如果块的总个数过多,就扫一遍所有的块,看看相邻的块能不能合并;不过实际上在操作的时候顺带着检查一下这个[l,r]的附近有没有可合并的区间即可,不过懒得写了。
12.栈
点击查看代码
#include <iostream>
#include <vector>
using std::cin;
using std::cout;
const int N = 1e5 + 10;
typedef long long ll;
struct Node
{
int l, r;
ll cnt;
ll rst;
int val;
ll sum;
} z[N << 2];
struct Q
{
int p;
ll x;
int y;
ll q;
};
#define root 1, m, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
int top = 0;
bool qr[N];
int stk[N << 2];
ll min[N << 2];
ll ans[N];
std::vector<int> id;
std::vector<Q> op[N];
ll query(int rt, ll k, int l, int r)
{
if (l == r)
return (k >= z[rt].cnt ? 0 : 1ll * z[rt].val * (z[rt].cnt - k));
int mid = (l + r) >> 1;
int ls = rt << 1;
int rs = rt << 1 | 1;
if (z[rs].cnt > k)
return z[rt].sum - z[rs].sum + query(rs, k, mid + 1, r);
else
return query(ls, k - z[rs].cnt + z[rs].rst, l, mid);
}
ll query1(int rt, ll k, int l, int r, ll t)
{
if (l == r)
return std::min(t, std::max(0ll, z[rt].cnt - k)) * z[rt].val;
int mid = (l + r) >> 1;
int ls = rt << 1;
int rs = rt << 1 | 1;
if (z[rs].cnt > k)
{
if (t <= (z[rs].rst >= z[ls].cnt ? 0 : z[ls].cnt - z[rs].rst))
return query1(ls, z[rs].rst, l, mid, t);
else
return z[rt].sum - z[rs].sum + query1(rs, k, mid + 1, r, t - (z[rs].rst >= z[ls].cnt ? 0 : z[ls].cnt - z[rs].rst));
}
else
return query1(ls, k - z[rs].cnt + z[rs].rst, l, mid, t);
}
void push_up(int rt, int l, int r)
{
int ls = rt << 1;
int rs = rt << 1 | 1;
int mid = (l + r) >> 1;
z[rt].cnt = z[rs].cnt + (z[rs].rst >= z[ls].cnt ? 0 : z[ls].cnt - z[rs].rst);
z[rt].rst = z[ls].rst + (z[rs].rst >= z[ls].cnt ? z[rs].rst - z[ls].cnt : 0);
z[rt].sum = z[rs].sum + query(ls, z[rs].rst, l, mid);
}
void modify(int l, int r, int rt, int p, ll x, int y)
{
if (l == r)
{
if (x > 0)
{
z[rt].cnt = x;
z[rt].rst = 0;
z[rt].sum = x * y;
z[rt].val = y;
}
else
{
z[rt].cnt = 0;
z[rt].rst = -x;
z[rt].sum = 0;
z[rt].val = 0;
}
return;
}
int mid = (l + r) >> 1;
if (p <= mid)
modify(lson, p, x, y);
else
modify(rson, p, x, y);
push_up(rt, l, r);
}
void qid(int l, int r, int rt, int nowl, int nowr)
{
if (nowl <= l && r <= nowr)
{
z[rt].l = l, z[rt].r = r;
id.push_back(rt);
return;
}
int mid = (l + r) >> 1;
if (nowl <= mid)
qid(lson, nowl, nowr);
if (nowr > mid)
qid(rson, nowl, nowr);
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; ++i)
{
int opt;
cin >> opt;
if (opt == 1)
{
int l, r, x, y;
cin >> l >> r >> x >> y;
op[l].push_back({i, x, y, 0});
if (r < n)
op[r + 1].push_back({i, 0, 0, 0});
}
else if (opt == 2)
{
int l, r;
ll w;
cin >> l >> r >> w;
op[l].push_back({i, -w, 0, 0});
if (r < n)
op[r + 1].push_back({i, 0, 0, 0});
}
else if (opt == 3)
{
int k;
ll p, q;
cin >> k >> p >> q;
op[k].push_back({i, q, 0, 1});
if (p > 1)
op[k].push_back({i, p - 1, 0, -1});
qr[i] = true;
}
}
for (int i = 1; i <= n; ++i)
{
for (auto it : op[i])
{
if (!it.q)
modify(root, it.p, it.x, it.y);
else
{
id.clear();
qid(root, 1, it.p);
top = 0;
for (int j = 0; j < (int)id.size(); ++j)
min[id[j]] = 0;
for (int j = 0; j < (int)id.size(); ++j)
{
ll now = z[id[j]].rst;
while (top && min[stk[top]] + now >= z[stk[top]].cnt)
now -= (z[stk[top]].cnt - min[stk[top]]), min[stk[top]] = z[stk[top]].cnt, top--;
if (top)
min[stk[top]] += now;
stk[++top] = id[j];
}
ll na = 0;
ll nowc = 0;
for (int j = 0; j < (int)id.size(); ++j)
{
if (nowc + z[id[j]].cnt - min[id[j]] <= it.x)
{
nowc += z[id[j]].cnt - min[id[j]];
na += query(id[j], min[id[j]], z[id[j]].l, z[id[j]].r);
}
else
{
na += query1(id[j], min[id[j]], z[id[j]].l, z[id[j]].r, it.x - nowc);
break;
}
}
ans[it.p] += na * it.q;
}
}
}
for (int i = 1; i <= m; ++i)
{
if (qr[i])
cout << ans[i] << '\n';
}
return 0;
}
ps:在用栈统计每个区间会被pop多少次的时候,我以前是这么写的:
for (int j = 0; j < (int)id.size(); ++j)
{
ll now = z[id[j]].rst;
while (top && min[stk[top]] + now >= z[stk[top]].cnt)
min[stk[top]] = z[stk[top]].cnt, now -= (z[stk[top]].cnt - min[stk[top]]), top--;
if (top)
min[stk[top]] += now;
stk[++top] = id[j];
}
但是显然是错的,因为在now减之前z[stk[top]].cnt已经被赋值成min[stk[top]]了,所以now一直减的都是0。

浙公网安备 33010602011771号