"BJOI2018" secondary summation on the chain (line segment tree)

https://loj.ac/problem/2513

Halal Questions

It may be considered to enumerate each element to count the coefficient of its occurrence * its weight.

The number of occurrences of \ (a [x] \) and \ (a [n-x + 1] \) is the same, so only half of the whole sequence is left.

First consider how many times \ (a [x] (x \ le (n + 1) / 2) \) will appear in length \ (y \) .

After discussion, it was found to be \ (min (x, y, n-y + 1) \)

Then suppose \ (y \ le (n + 1) / 2 \) , the greater part is the same.

The last thing is to ask for such a thing \ ((r <= (n + 1) / 2) \) :
\ (\ sum_ {i = 1} ^ {(n + 1) / 2} a [i] * \ sum_ { j = 1} ^ {r} min (i, j) \)

Disassemble the formula and find that maintaining the interval sum of \ (a [i] * i ^ {0..2} \) is just fine.

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;

const int mo = 1e9 + 7;

ll ksm(ll x, ll y) {
	ll s = 1;
	for(; y; y /= 2, x = x * x % mo)
		if(y & 1) s = s * x % mo;
	return s;
}

const ll ni2 = ksm(2, mo - 2);

const int N = 2e5 + 5;

int n, m, n0, op, x, y, z;

#define i0 i + i
#define i1 i + i + 1 
ll g[N * 4][3], t[N * 4][3], lz[N * 4];

void bt(int i, int x, int y) {
	if(x == y) {
		g[i][0] = 1;
		g[i][1] = x;
		g[i][2] = (ll) x * x % mo;
		return;
	}
	int m = x + y >> 1;
	bt(i0, x, m); bt(i1, m + 1, y);
	fo(j, 0, 2) g[i][j] = (g[i0][j] + g[i1][j]) % mo;
}
int pl, pr, px;
void jia(int i, int px) {
	fo(j, 0, 2) t[i][j] = (t[i][j] + g[i][j] * px) % mo;
	lz[i] = (lz[i] + px) % mo;
}
void down(int i) {
	if(lz[i]) jia(i0, lz[i]), jia(i1, lz[i]), lz[i] = 0;
}
void add(int i, int x, int y) {
	if(y < pl || x > pr) return;
	if(x >= pl && y <= pr) {
		jia(i, px);
		return;
	}
	int m = x + y >> 1; down(i);
	add(i0, x, m); add(i1, m + 1, y);
	fo(j, 0, 2) t[i][j] = (t[i0][j] + t[i1][j]) % mo;
}
ll py[3];
void ft(int i, int x, int y) {
	if(y < pl || x > pr) return;
	if(x >= pl && y <= pr) {
		fo(j, 0, 2) py[j] = (py[j] + t[i][j]) % mo;
		return;
	}
	int m = x + y >> 1; down(i);
	ft(i0, x, m); ft(i1, m + 1, y);
}

void xiu(int x, int y, int z) {
	if(x <= n0) {
		pl = x, pr = min(y, n0), px = z;
		add(1, 1, n0);
	}
	if(y > n0) {
		pl = n - y + 1, pr = n - max(x, n0 + 1) + 1; px = z;
		add(1, 1, n0);
	}
}

ll calc(int r) {
	ll ans = 0;
	
	pl = 1, pr = r; fo(j, 0, 2) py[j] = 0;
	ft(1, 1, n0);
	ans = (ans + (py[2] + py[1]) * ni2 % mo - py[2] + py[1] * r + mo) % mo;
	
	pl = r + 1, pr = n0; fo(j, 0, 2) py[j] = 0;
	ft(1, 1, n0);
	ans = (ans + py[0] * ((ll) r * (r + 1) / 2 % mo)) % mo;
	
	return ans;
}

ll qry(int r) {
	if(r <= n0) return calc(r);
	return (calc(n0) + (n % 2 == 1 ? calc(n0 - 1) : calc(n0)) - calc(n - r) + mo) % mo;
}

int main() {
	scanf("%d %d", &n, &m);
	n0 = (n + 1) / 2;
	bt(1, 1, n0);
	fo(i, 1, n) {
		scanf("%d", &x);
		xiu(i, i, x);
	}
	fo(ii, 1, m) {
		scanf("%d %d %d", &op, &x, &y);
		if(op == 1) {
			scanf("%d", &z);
			if(x > y) swap(x, y);
			xiu(x, y, z);
		} else {
			ll s = (qry(y) - qry(x - 1) + mo) % mo;
			pp("%lld\n", s);
		}
	}
}

Guess you like

Origin www.cnblogs.com/coldchair/p/12699032.html