B
顺序发现线段树无法维护,逆序之后每个输入对(pos,val)的pos + 1既是队列前面需要的空位,线段树维护还留下的空位
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn << 2], lzy[maxn << 2], n;
void pushUp(int rt) { a[rt] = a[rt << 1] + a[rt << 1 | 1]; }
void build(int rt = 1, int l = 1, int r = n) {
if(l == r) {
a[rt] = 1;
lzy[rt] = 0;
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushUp(rt);
}
void update(int pos, int val, int rt = 1, int l = 1, int r = n) {
if(l == r) {
a[rt]--;
lzy[rt] = val;
return;
}
int mid = l + r >> 1;
if(a[rt << 1] >= pos) update(pos, val, rt << 1, l, mid);
else update(pos - a[rt << 1], val, rt << 1 | 1, mid + 1, r);
pushUp(rt);
}
vector<int> ans;
void solve(int rt = 1, int l = 1, int r = n) {
if(l == r) {
ans.push_back(lzy[rt]);
return;
}
int mid = l + r >> 1;
solve(rt << 1, l, mid);
solve(rt << 1 | 1, mid + 1, r);
}
pair<int, int> in[maxn];
int main()
{
while(~scanf("%d", &n)) {
for(int i = 1; i <= n; ++i)
scanf("%d%d", &in[i].first, &in[i].second);
build();
for(int i = n; i >= 1; --i) {
update(in[i].first + 1, in[i].second);
}
ans.clear();
solve();
for(int i = 0; i < n; ++i) i == 0 ? printf("%d", ans[i]) : printf(" %d", ans[i]);
printf("\n");
}
}
C
线段树区间更新
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 5e4 + 5;
int n, m;
struct node {
int sum, lsum, rsum, lzy;
} a[maxn << 2];
void pushUp(int rt, int l, int r) {
if(l == r) return;
a[rt].sum = max(a[rt << 1].sum, a[rt << 1 | 1].sum);
a[rt].lsum = a[rt << 1].lsum;
a[rt].rsum = a[rt << 1 | 1].rsum;
int mid = l + r >> 1;
if(a[rt << 1].lsum == mid - l + 1) a[rt].lsum += a[rt << 1 | 1].lsum;
if(a[rt << 1 | 1].rsum == r - mid) a[rt].rsum += a[rt << 1].rsum;
a[rt].sum = max(a[rt].sum, a[rt << 1].rsum + a[rt << 1 | 1].lsum);
}
void pushDown(int rt, int l, int r) {
if(a[rt].lzy == -1) return;
if(l == r) return;
int mid = l + r >> 1;
a[rt << 1].lzy = a[rt << 1 | 1].lzy = a[rt].lzy;
if(a[rt].lzy) {
a[rt << 1].sum = a[rt << 1].lsum = a[rt << 1].rsum = mid - l + 1;
a[rt << 1 | 1].sum = a[rt << 1 | 1].lsum = a[rt << 1 | 1].rsum = r - mid;
}
else {
a[rt << 1].sum = a[rt << 1].lsum = a[rt << 1].rsum = 0;
a[rt << 1 | 1].sum = a[rt << 1 | 1].lsum = a[rt << 1 | 1].rsum = 0;
}
a[rt].lzy = -1;
}
void build(int rt = 1, int l = 1, int r = n) {
a[rt].lzy = -1;
if(l == r) {
a[rt].sum = a[rt].lsum = a[rt].rsum = 1;
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushUp(rt, l, r);
}
int query(int k, int rt = 1, int l = 1, int r = n) {
pushDown(rt, l, r);
if(l == r) return l;
int mid = l + r >> 1;
if(a[rt << 1].sum >= k) return query(k, rt << 1, l, mid);
else if(a[rt << 1].rsum + a[rt << 1 | 1].lsum >= k) return mid - a[rt << 1].rsum + 1;
else return query(k, rt << 1 | 1, mid + 1, r);
}
void update(int L, int R, int op, int rt = 1, int l = 1, int r = n) {
if(L <= l && r <= R) {
if(op) {
a[rt].lzy = 1;
a[rt].sum = a[rt].lsum = a[rt].rsum = r - l + 1;
}
else {
a[rt].lzy = 0;
a[rt].sum = a[rt].lsum = a[rt].rsum = 0;
}
return;
}
pushDown(rt, l, r);
int mid = l + r >> 1;
if(mid >= L) update(L, R, op, rt << 1, l, mid);
if(mid < R) update(L, R, op, rt << 1 | 1, mid + 1, r);
pushUp(rt, l, r);
}
int main()
{
scanf("%d%d", &n, &m);
build();
for(int i = 0; i < m; ++i) {
int op, x, y;
scanf("%d", &op);
if(op == 1) {
scanf("%d", &x);
if(a[1].sum < x) {
printf("0\n");
}
else {
int res = query(x);
update(res, res + x - 1, 0);
printf("%d\n", res);
}
}
else {
scanf("%d%d", &x, &y);
update(x, min(x + y - 1, n), 1);
}
}
}
D
线段树扫描线
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 2000 + 5;
int n;
vector<double> hsh;
int getId(double x) { return lower_bound(hsh.begin(), hsh.end(), x) - hsh.begin(); }
struct in_node {
double l, r, h;
int flg;
in_node() {}
in_node(double _l, double _r, double _h, int _flg) : l(_l), r(_r), h(_h), flg(_flg) {}
bool operator <(const in_node& x) const {
return h < x.h;
}
} in[maxn << 1];
struct segmentTreeNode {
int cnt;
double len;
} tre[maxn << 2];
void pushup(int rt, int l, int r) {
if(tre[rt].cnt) tre[rt].len = hsh[r + 1] - hsh[l];
else if(l == r) tre[rt].len = 0;
else tre[rt].len = tre[rt << 1].len + tre[rt << 1 | 1].len;
}
void build(int rt = 1, int l = 0, int r = hsh.size() - 1) {
tre[rt].cnt = tre[rt].len = 0;
if(l == r) return;
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
}
void update(int L, int R, int val, int rt = 1, int l = 0, int r = hsh.size() - 1) {
if(L <= l && r <= R) {
tre[rt].cnt += val;
pushup(rt, l, r);
return;
}
int mid = l + r >> 1;
if(mid >= L) update(L, R, val, rt << 1, l, mid);
if(mid < R) update(L, R, val, rt << 1 | 1, mid + 1, r);
pushup(rt, l, r);
}
int main()
{
int cas = 1;
while(~scanf("%d", &n)) {
if(n == 0) break;
hsh.clear();
int tot = 0;
double lx, ly, rx, ry;
for(int i = 0; i < n; ++i) {
scanf("%lf%lf%lf%lf", &lx, &ly, &rx, &ry);
hsh.push_back(lx);
hsh.push_back(rx);
in[tot++] = in_node(lx, rx, ly, 1);
in[tot++] = in_node(lx, rx, ry, -1);
}
sort(hsh.begin(), hsh.end());
hsh.erase(unique(hsh.begin(), hsh.end()), hsh.end());
build();
sort(in, in + tot);
double area = 0;
for(int i = 0; i < tot; ++i) {
update(getId(in[i].l), getId(in[i].r) - 1, in[i].flg);
area += tre[1].len * (in[i + 1].h - in[i].h);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", cas++, area);
}
}
F
主席树区间第k大
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 100000 + 5;
vector<int> hsh;
int getId(int x) { return lower_bound(hsh.begin(), hsh.end(), x) - hsh.begin(); }
int root[maxn], cnt;
struct seg {
int lson, rson, num;
} tre[maxn * 40];
void update(int l, int r, int& rt, int& pre, int pos) {
rt = ++cnt;
tre[rt] = tre[pre];
tre[rt].num++;
if(l == r) return;
int mid = l + r >> 1;
if(pos <= mid) update(l, mid, tre[rt].lson, tre[pre].lson, pos);
else update(mid + 1, r, tre[rt].rson, tre[pre].rson, pos);
}
int query(int l, int r, int pre, int now, int k) {
if(l == r) return l;
int mid = l + r >> 1;
int num = tre[tre[now].lson].num - tre[tre[pre].lson].num;
if(k <= num) return query(l, mid, tre[pre].lson, tre[now].lson, k);
else return query(mid + 1, r, tre[pre].rson, tre[now].rson, k - num);
}
int a[maxn];
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m)) {
hsh.clear();
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
hsh.push_back(a[i]);
}
sort(hsh.begin(), hsh.end());
hsh.erase(unique(hsh.begin(), hsh.end()), hsh.end());
root[0] = cnt = 0;
for(int i = 1; i <= n; ++i) {
update(0, n - 1, root[i], root[i - 1], getId(a[i]));
}
while(m--) {
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
printf("%d\n", hsh[query(0, n - 1, root[l - 1], root[r], k)]);
}
}
}
G
线段树更新约瑟夫环
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 5e5 + 5;
int n, k;
int ip[] = {1, 2, 4, 6, 12, 24, 36, 48, 60, 120, 180, 240, 360, 720,
840, 1260, 1680, 2520, 5040, 7560, 10080, 15120, 20160,
25200, 27720, 45360, 50400, 55440, 83160, 110880,
166320, 221760, 277200, 332640, 498960, 500001
}; //反素数
int div1[] = {1, 2, 3, 4, 6, 8, 9, 10, 12, 16, 18, 20, 24, 30, 32, 36,
40, 48, 60, 64, 72, 80, 84, 90, 96, 100, 108, 120,
128, 144, 160, 168, 180, 192, 200
};//反素数对应的约数个数
struct in_node {
char name[15];
int val;
} in[maxn];
int tre[maxn << 2];
void pushup(int rt) {
tre[rt] = tre[rt << 1] + tre[rt << 1 | 1];
}
void build(int rt = 1, int l = 1, int r = n) {
if(l == r) {
tre[rt] = 1;
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushup(rt);
}
int update(int k, int rt = 1, int l = 1, int r = n) {
if(l == r) {
tre[rt] = 0;
return l;
}
int mid = l + r >> 1;
int ret;
if(tre[rt << 1] >= k) ret = update(k, rt << 1, l, mid);
else ret = update(k - tre[rt << 1], rt << 1 | 1, mid + 1, r);
pushup(rt);
return ret;
}
int main()
{
while(~scanf("%d%d", &n, &k)) {
for(int i = 1; i <= n; ++i)
scanf("%s%d", &in[i].name, &in[i].val);
int m, cnt;
for(int i = 0; ip[i] <= n; ++i) {
m = ip[i];
cnt = div1[i];
}
build();
int res = n, pos;
for(int i = 0; i < m; ++i) {
res--;
pos = update(k);
if(res == 0) break;
if(in[pos].val >= 0) k = (k - 1 + in[pos].val - 1) % res + 1;
else k = ((k - 1 + in[pos].val) % res + res) % res + 1;
}
printf("%s %d\n", in[pos].name, cnt);
}
}
H
旋转中序遍历
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int mod = 1000000007;
typedef long long ll;
int n, son[maxn][2], fa[maxn], idx[maxn], ral[maxn], lr[maxn][2], w[maxn];
ll val[maxn], mul[maxn << 2];
void dfs(int x, int& dfn) {
val[x] = w[x];
if(son[x][0]) dfs(son[x][0], dfn), lr[x][0] = lr[son[x][0]][0], val[x] += val[son[x][0]];
else lr[x][0] = dfn + 1;
idx[x] = ++dfn;
ral[dfn] = x;
if(son[x][1]) dfs(son[x][1], dfn), lr[x][1] = lr[son[x][1]][1], val[x] += val[son[x][1]];
else lr[x][1] = dfn;
val[x] %= mod;
}
void pushup(int rt) {
mul[rt] = mul[rt << 1] * mul[rt << 1 | 1] % mod;
}
void build(int rt = 1, int l = 1, int r = n) {
if(l == r) {
mul[rt] = val[ral[l]];
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
pushup(rt);
}
ll query(int L, int R, int rt = 1, int l = 1, int r = n) {
if(L <= l && r <= R) return mul[rt];
int mid = l + r >> 1;
ll res = 1;
if(L <= mid) res = res * query(L, R, rt << 1, l, mid) % mod;
if(mid < R) res = res * query(L, R, rt << 1 | 1, mid + 1, r) % mod;
return res;
}
void update(int pos, ll v, int rt = 1, int l = 1, int r = n) {
if(l == r) {
mul[rt] = v;
return;
}
int mid = l + r >> 1;
if(pos <= mid) update(pos, v, rt << 1, l, mid);
else update(pos, v, rt << 1 | 1, mid + 1, r);
pushup(rt);
}
void LR(int x, int op) {
if(son[x][op] == 0) return;
int y = son[x][op];
int bb = son[y][op ^ 1], cc = son[y][op];
son[x][op] = bb;
fa[bb] = x;
int xx = fa[x];
if(son[xx][0] == x) son[xx][0] = y;
else son[xx][1] = y;
fa[y] = xx;
son[y][op ^ 1] = x;
fa[x] = y;
if(bb) lr[x][op] = lr[bb][op];
else lr[x][op] = idx[x];
lr[y][op ^ 1] = lr[x][op ^ 1];
if(bb) val[x] = val[x]-val[y]+val[bb];
else val[x] = val[x]-val[y];
if(cc) val[y] = val[x]+val[cc]+w[y];
else val[y] = val[x]+w[y];
update(idx[x], val[x]);
update(idx[y], val[y]);
}
int main()
{
int t, m;
scanf("%d", &t);
for(int cas = 1; cas <= t; ++cas) {
printf("Case #%d:\n", cas);
scanf("%d%d", &n, &m);
memset(fa, 0, sizeof(fa));
son[0][0] = son[0][1] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d%d%d", &w[i], &son[i][0], &son[i][1]);
fa[son[i][0]] = fa[son[i][1]] = i;
}
int dfn = 0;
dfs(1, dfn);
build();
while(m--) {
int op, x;
scanf("%d%d", &op, &x);
if(op == 2) printf("%lld\n", query(lr[x][0], lr[x][1]));
else LR(x, op);
}
}
}