luogu P2221 [HAOI2012]高速公路
这种思博题有什么好写的呀
直接考虑每条边的贡献,然后把贡献的式子拆开,再维护一下就好了
你们随便看看吧
思博题
线段树维护3个值就好了QWQ
code:
#include<bits/stdc++.h>
#define N 200005
#define int long long
using namespace std;
int gcd(int x, int y) {
return y? gcd(y, x % y) : x;
}
struct A {
int s, s1, s2, tag;
}a[N << 4];
int sum1[N], sum2[N];
void update(int rt) {
a[rt].s = a[rt << 1].s + a[rt << 1 | 1].s;
a[rt].s1 = a[rt << 1].s1 + a[rt << 1 | 1].s1;
a[rt].s2 = a[rt << 1].s2 + a[rt << 1 | 1].s2;
}
void pushdown(int rt, int l, int r) {
if(a[rt].tag) {
int mid = (l + r) >> 1;
a[rt << 1].tag += a[rt].tag;
a[rt << 1 | 1].tag += a[rt].tag;
a[rt << 1].s += (mid - l + 1) * a[rt].tag;
a[rt << 1 | 1].s += (r - mid) * a[rt].tag;
a[rt << 1].s1 += (sum1[mid] - sum1[l - 1]) * a[rt].tag;
a[rt << 1 | 1].s1 += (sum1[r] - sum1[mid]) * a[rt].tag;
a[rt << 1].s2 += (sum2[mid] - sum2[l - 1]) * a[rt].tag;
a[rt << 1 | 1].s2 += (sum2[r] - sum2[mid]) * a[rt].tag;
a[rt].tag = 0;
}
}
void add(int rt, int l, int r, int L, int R, int o) {
pushdown(rt, l, r);
if(L <= l && r <= R) {
a[rt].tag += o;
a[rt].s += (r - l + 1) * o;
a[rt].s1 += (sum1[r] - sum1[l - 1]) * o;
a[rt].s2 += (sum2[r] - sum2[l - 1]) * o;
return;
}
int mid = (l + r) >> 1;
if(L <= mid) add(rt << 1, l, mid, L, R, o);
if(R > mid) add(rt << 1 | 1, mid + 1, r, L, R, o);
update(rt);
}
A query(int rt, int l, int r, int L, int R) {
pushdown(rt, l, r);
if(L <= l && r <= R) return a[rt];
int mid = (l + r) >> 1;
A ret = {0, 0, 0, 0};
if(L <= mid) ret = query(rt << 1, l, mid, L, R);
if(R > mid) {
A rett = query(rt << 1 | 1, mid + 1, r, L, R);
ret.s += rett.s, ret.s1 += rett.s1, ret.s2 += rett.s2;
}
return ret;
}
int n, m;
signed main() {
scanf("%lld%lld", &n, &m); n --;
for(int i = 1; i <= n; i ++) sum1[i] = sum1[i - 1] + i, sum2[i] = sum2[i - 1] + i * i;
while(m --) {
char c;
int l, r, x;
scanf(" %c", &c);
if(c == 'C') {
scanf("%lld%lld%lld", &l, &r, &x); r --;
add(1, 1, n, l, r, x);
} else {
scanf("%lld%lld", &l, &r); r --;
A ha = query(1, 1, n, l, r);
int fz = -(l*r+l-r-1)*ha.s + (r+l)*ha.s1 - ha.s2;
int fm = (r - l + 2) * (r - l + 1) / 2;
int d = gcd(fz, fm);
fz /= d, fm /= d;
printf("%lld/%lld\n", fz, fm);
}
}
return 0;
}
坑点
long long