线段树
最大数
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int m, p, t, pos = 0;
int ans = 0;
typedef long long ll;
struct segement_tree
{
int l, r, w;
}tr[N << 2];
void push_up(int p)
{
tr[p].w = max(tr[p << 1].w, tr[p << 1 | 1].w);
return ;
}
void update (int p, int l, int r, int x, int val)
{
if(l == r)
{
tr[p].w = val;
return ;
}
int mid = l + r >> 1;
if(x <= mid) update(p << 1, l, mid, x, val);
else update(p << 1 | 1, mid + 1, r, x, val);
push_up(p);
return ;
}
int query(int p, int l, int r, int L, int R)
{
if(L <= l && r <= R) return tr[p].w;
if(l > R || r < L) return 0;
int mid = l + r >> 1;
return max(query(p << 1, l, mid, L, R), query(p << 1 | 1, mid + 1, r, L, R));
}
int main()
{
scanf("%d %d", &m, &p);
char s[2];
while(m --)
{
scanf("%s %d", s, &t);
if(s[0] == 'A')
{
t = ((ll)t + ans) % p, pos ++;
update(1, 1, N - 5, pos, t);
}
else if(s[0] == 'Q') ans = query(1, 1, N - 5, pos - t + 1, pos), printf("%d\n", ans);
}
return 0;
}
你能回答这些问题吗
build_tree函数里面记得push_up一下
#include <bits/stdc++.h>
using namespace std;
const int N = 500005, inf = 200000000;
int n, m, a[N];
struct segement_tree
{
int lw, rw, w, sum;
}tr[N << 2];
segement_tree push_up(segement_tree x, segement_tree y)
{
segement_tree t;
t.lw = max(x.lw, x.sum + y.lw);
t.rw = max(y.rw, y.sum + x.rw);
t.sum = x.sum + y.sum;
t.w = max(max(x.w, y.w), x.rw + y.lw);
return t;
}
void build_tree(int p, int l, int r)
{
if(l == r)
{
tr[p].w = tr[p].lw = tr[p].rw = tr[p].sum = a[l];
return ;
}
int mid = l + r >> 1;
build_tree(p << 1, l, mid), build_tree(p << 1 | 1, mid + 1, r);
tr[p] = push_up(tr[p << 1], tr[p << 1 | 1]);
return ;
}
void update(int p, int l, int r, int x, int k)
{
if(l == r)
{
tr[p].w = tr[p].lw = tr[p].rw = tr[p].sum = k;
return ;
}
int mid = l + r >> 1;
if(x <= mid) update(p << 1, l, mid, x, k);
else update(p << 1 | 1, mid + 1, r, x, k);
tr[p] = push_up(tr[p << 1], tr[p << 1 | 1]);
return ;
}
segement_tree query(int p, int l, int r, int L, int R)
{
if(L <= l && r <= R) return tr[p];
if(l > R || r < L) return (segement_tree){-inf, -inf, -inf, 0};
int mid = l + r >> 1;
segement_tree a = query(p << 1, l, mid, L, R), b = query(p << 1 | 1, mid + 1, r, L, R);
return push_up(a, b);
}
int main()
{
scanf("%d %d", &n, &m);
for (int i =1; i <= n; ++ i) scanf("%d", &a[i]);
build_tree(1, 1, n);
while(m --)
{
int opt, x, y;
scanf("%d %d %d", &opt, &x, &y);
if(opt == 2) update(1, 1, n, x, y);
else
{
if(x > y) swap(x, y);
printf("%d\n", query(1, 1, n, x, y).w);
}
}
return 0;
}
区间最大公约数
注意数组不要开小了,要是四倍。不是结构体形式的千万别忘记了。
#include <bits/stdc++.h>
using namespace std;
const int N = 500005;
typedef long long ll;
ll a[N], sum[N << 2], sm[N << 2];
int n, m;
int gcd(int x, int y)
{
if(y == 0) return x;
return gcd(y, x % y);
}
void push_up(int p)
{
sum[p] = gcd(sum[p << 1], sum[p << 1 | 1]);
sm[p] = sm[p << 1] + sm[p << 1 | 1];
return ;
}
void build_tree(int p, int l, int r)
{
if(l == r)
{
sum[p] = a[l] - a[l - 1];
sm[p] = sum[p];
return ;
}
int mid = l + r >> 1;
build_tree(p << 1, l, mid), build_tree(p << 1 | 1, mid + 1, r);
push_up(p);
return ;
}
void update(int p, int l, int r, int x, ll k)
{
if(l == r)
{
sum[p] += k;
sm[p] += k;
return ;
}
int mid = l + r >> 1;
if(x <= mid) update(p << 1, l, mid, x, k);
else update(p << 1 | 1, mid + 1, r, x, k);
push_up(p);
return ;
}
ll query1(int p, int l, int r, int L, int R)
{
if(L <= l && r <= R) return sum[p];
int mid = l + r >> 1;
if(L <= mid && R > mid) return gcd(query1(p << 1, l, mid, L, R), query1(p << 1 | 1, mid + 1, r, L, R));
else if(L <= mid) return query1(p << 1, l, mid, L, R);
else return query1(p << 1 | 1, mid + 1, r, L, R);
}
ll query2(int p, int l, int r, int L, int R)
{
if(L <= l && r <= R) return sm[p];
if(l > R || r < L) return 0;
int mid = l + r >> 1;
return query2(p << 1, l, mid, L, R) + query2(p << 1 | 1, mid + 1, r, L, R);
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++ i) scanf("%lld", &a[i]);
build_tree(1, 1, n);
while(m --)
{
char s[2];
int l, r;
scanf("%s %d %d", s, &l, &r);
if(s[0] == 'Q')
{
if(l == r) printf("%lld\n", query2(1, 1, n, 1, l));
else printf("%lld\n", abs(gcd(query2(1, 1, n, 1, l), query1(1, 1, n, l + 1, r))));
}
else
{
ll d;
scanf("%lld", &d);
update(1, 1, n, l, d);
if(r <= n - 1) update(1, 1, n, r + 1, -d);
}
}
return 0;
}
一个简单的整数问题2
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
typedef long long ll;
int n, lz[N << 2], m, a[N];
ll sum[N << 2];
void push_up(int p)
{
sum[p] = sum[p << 1] + sum[p << 1 | 1];
return ;
}
void build_tree(int p, int l, int r)
{
if(l == r)
{
sum[p] = a[l];
return ;
}
int mid = l + r >> 1;
build_tree(p << 1, l, mid), build_tree(p << 1 | 1, mid + 1, r);
push_up(p);
return ;
}
void push_down(int p, int l, int r)
{
if(!lz[p]) return ;
int mid = l + r >> 1;
sum[p << 1] += (ll)(mid - l + 1) * lz[p];
sum[p << 1 | 1] += (ll)(r - mid) * lz[p];
lz[p << 1] += lz[p], lz[p << 1 | 1] += lz[p];
lz[p] = 0;
return ;
}
void update(int p, int l, int r, int L, int R, int d)
{
if(L <= l && r <= R)
{
sum[p] = sum[p] + (ll)(r - l + 1) * d;
lz[p] += d;
return ;
}
if(l > R || r < L) return ;
push_down(p, l, r);
int mid = l + r >> 1;
update(p << 1, l, mid, L, R, d);
update(p << 1 | 1, mid + 1, r, L, R, d);
push_up(p);
}
ll query(int p, int l, int r, int L, int R)
{
if(L <= l && r <= R) return sum[p];
if(l > R || r < L) return 0;
int mid = l + r >> 1;
push_down(p, l, r);
return query(p << 1, l, mid, L, R) + query(p << 1 | 1, mid + 1, r, L, R);
}
int main()
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]);
build_tree(1, 1, n);
while(m --)
{
char s[2];
int l, r, d;
scanf("%s", s);
if(s[0] == 'C')
{
scanf("%d %d %d", &l, &r, &d);
update(1, 1, n, l, r, d);
}
else
{
scanf("%d %d", &l, &r);
printf("%lld\n", query(1, 1, n, l, r));
}
}
}
亚特兰蒂斯
垃圾题,不想用特殊性质了,直接暴力(线段树是假的)。
#include <bits/stdc++.h>
using namespace std;
typedef double db;
const int N = 40005;
db lsh[N];
int tot = 0, cnt = 0, n;
db ans = 0, pre;
struct data
{
db x, l, r;
int opt;
bool operator < (const data &a) const {return x < a.x; }
}p[N];
const int inf = 0x3f3f3f3f;
int mn[N << 2], lz[N << 2];
db sum[N << 2];
void push_up(int p)
{
mn[p] = min(mn[p << 1], mn[p << 1 | 1]);
sum[p] = sum[p << 1] + sum[p << 1 | 1];
return ;
}
void push_down(int p, int l, int r)
{
if(!lz[p]) return;
int mid = l + r >> 1;
mn[p << 1] += lz[p], mn[p << 1 | 1] += lz[p];
lz[p << 1] += lz[p], lz[p << 1 | 1] += lz[p];
lz[p] = 0;
return ;
}
void build_tree(int p, int l, int r)
{
lz[p] = 0;
if(l == r)
{
mn[p] = 0, sum[p] = 0;
return ;
}
int mid = l + r >> 1;
build_tree(p << 1, l, mid), build_tree(p << 1 | 1, mid + 1, r);
push_up(p);
return ;
}
void update(int p, int l, int r, int L, int R, int k)
{
if(L <= l && r <= R)
{
lz[p] += k;
mn[p] += k;
return ;
}
if(r < L || l > R) return ;
int mid = l + r >> 1;
push_down(p, l, r);
update(p << 1, l, mid, L, R, k);
update(p << 1 | 1, mid + 1, r, L, R, k);
push_up(p);
}
int main()
{
int T = 0;
while(scanf("%d", &n) != EOF)
{
if(!n) break;
cnt = tot = 0;
T ++;
for (int i = 1; i <= n; ++ i)
{
db x, y, a, b;
scanf("%lf %lf %lf %lf", &x, &y, &a, &b);
lsh[++ cnt] = y, lsh[++ cnt] = b;
p[++ tot].x = x, p[tot].l = y, p[tot].r = b, p[tot].opt = 1;
p[++ tot].x = a, p[tot].l = y, p[tot].r = b, p[tot].opt = -1;
}
sort(lsh + 1, lsh + cnt + 1);
cnt = unique(lsh + 1, lsh + cnt + 1) - lsh - 1;
sort(p + 1, p + tot + 1);
ans = 0.0, pre = 0.0;
build_tree(1, 1, cnt);
for (int i = 1; i <= tot; ++ i)
{
int l = lower_bound(lsh + 1, lsh + cnt + 1, p[i].l) - lsh;
int r = lower_bound(lsh + 1, lsh + cnt + 1, p[i].r) - lsh;
if(p[i].x != p[i - 1].x) pre = query(1, 1, cnt, 1, cnt), ans = ans + pre * (p[i].x - p[i - 1].x);
update(1, 1, cnt, l, r - 1, p[i].opt);
}
printf("Test case #%d\n", T);
printf("Total explored area: %.2lf\n\n", ans);
}
return 0;
}
维护序列
分析:懒标记就是之前需要操作的*c+d,现在我们要在原来的基础上进行新的操作。对于一个位置x而言
x * c + d如果我们进行的是乘法操作,那么答案这个数字就会变成(x * c +d) * y = x * c * y + d * y,如果我们进行新的加法操作,这个数字就会变成x * c +d + y,我们只需要比较这两个数字和x * c +d在哪一些方面有变化就可以了。这就是先进行乘法操作的好处。
如果我们采用的形式是(x + d) * c = x * c + d * c的话,x * c + d * c+ y是无法变成一个方便的类似的形式的。
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
typedef long long ll;
int n, mod, mul[N << 2], ad[N << 2], sum[N << 2], m, a[N];
void push_up(int p)
{
sum[p] = (ll)(sum[p << 1] + sum[p << 1 | 1]) % mod;
return ;
}
void push_down(int p, int l, int r)
{
if(mul[p] == 1 && !ad[p]) return ;
int mid = l + r >> 1;
sum[p << 1] = ((ll)sum[p << 1] * mul[p] % mod + (ll)ad[p] * (mid - l + 1) % mod) % mod;
sum[p << 1 | 1] = ((ll)sum[p << 1 | 1] * mul[p] % mod + (ll)ad[p] * (r - mid) % mod) % mod;
mul[p << 1] = (ll)mul[p << 1] * mul[p] % mod;
mul[p << 1 | 1] = (ll)mul[p << 1 | 1] * mul[p] % mod;
ad[p << 1] = ((ll)ad[p << 1] * mul[p] % mod + ad[p]) % mod;
ad[p << 1 | 1] = ((ll)ad[p << 1 | 1] * mul[p] % mod + ad[p]) % mod;
ad[p] = 0, mul[p] = 1;
return ;
}
void build_tree(int p, int l, int r)
{
mul[p] = 1, ad[p] = 0;
if(l == r)
{
sum[p] = a[l];
return ;
}
int mid = l + r >> 1;
build_tree(p << 1, l, mid), build_tree(p << 1 | 1, mid + 1, r);
push_up(p);
return ;
}
void update (int p, int l, int r, int L, int R, int a, int b)
{
if(L <= l && r <= R)
{
sum[p] = ((ll)sum[p] * b % mod + (ll)a * (r - l + 1) % mod) % mod;
mul[p] = (ll)mul[p] * b % mod;
ad[p] = ((ll)ad[p] * b % mod + a) % mod;
return ;
}
if(l > R || r < L) return ;
int mid = l + r >> 1;
push_down(p, l, r);
update(p << 1, l, mid, L, R, a, b);
update(p << 1 | 1, mid + 1, r, L, R, a, b);
push_up(p);
return ;
}
int query(int p, int l, int r, int L, int R)
{
if(L <= l && r <= R) return sum[p];
if(l > R || r < L) return 0;
int mid = l + r >> 1;
push_down(p, l, r);
return ((ll)query(p << 1, l, mid, L, R) + query(p << 1 | 1, mid + 1, r, L, R)) % mod;
}
int main()
{
scanf("%d %d", &n, &mod);
for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]);
build_tree(1, 1, n);
scanf("%d", &m);
while(m --)
{
int opt, t, g, c;
scanf("%d %d %d", &opt, &t, &g);
if(opt == 1)
{
scanf("%d", &c);
update(1, 1, n, t, g, 0, c);
}
else if(opt == 2)
{
scanf("%d", &c);
update(1, 1, n, t, g, c, 1);
}
else printf("%d\n", query(1, 1, n, t, g));
}
}

浙公网安备 33010602011771号