[Sdoi2017]相关分析 [线段树]

[Sdoi2017]相关分析

题意:沙茶线段树


md其实我考场上还剩一个多小时写了40分

其实当时写正解也可以吧1h也就写完了不过还要拍一下

正解代码比40分短2333

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long ll;
#define fir first
#define sec second
#define lc x<<1
#define rc x<<1|1
#define mid ((l+r)>>1)
#define lson lc, l, mid
#define rson rc, mid+1, r

const int N=1e5+5, INF=1e9, M=1e5+5;
inline int read() {
	char c=getchar(); int x=0, f=1;
	while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
	while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
	return x*f;
}

int n, Q, op,  ql, qr;
double a[N], b[N], s, w;

namespace seg {
	struct meow{
		double a, b, c, a2, ta, tb, sa, sb;
		meow(): sa(-1), sb(-1) {}
		meow(double a, double b, double c, double a2): a(a), b(b), c(c), a2(a2), ta(0), tb(0), sa(-1), sb(-1){}
	} t[N<<2];
	meow operator + (const meow &x, const meow &y) { return meow(x.a + y.a, x.b + y.b, x.c + y.c, x.a2 + y.a2); }

	inline double cal2(double n) {return n * (n+1) * (2*n + 1) / 6;}
	inline void _set(int x, int l, int r, double s, double w) {
		meow &now = t[x];
		now.sa = s; now.sb = w;
		now.ta = now.tb = 0; // clear
		double len = r-l+1, val = (l+r) * len / 2;
		now.a = len * s + val;
		now.b = len * w + val;
		double val2 = cal2(r) - cal2(l-1);
		now.c =  val2 + val * (s + w) + s * w * len;
		now.a2 = val2 + val * (s + s) + s * s * len;
	}
	inline void _add(int x, int l, int r, double s, double w) {
		meow &now = t[x];
		now.ta += s; now.tb += w;
		double len = r-l+1;
		now.c += now.a * w + now.b * s + s * w * len;
		now.a2 += now.a * (s + s) + s * s * len; 
		now.a += len * s;
		now.b += len * w;
	}

	inline void pushdn(int x, int l, int r) {
		if(t[x].sa != -1 || t[x].sb != -1) {
			_set(lson, t[x].sa, t[x].sb);
			_set(rson, t[x].sa, t[x].sb);
			t[x].sa = t[x].sb = -1;
		} 
		if(t[x].ta || t[x].tb) {
			_add(lson, t[x].ta, t[x].tb);
			_add(rson, t[x].ta, t[x].tb);
			t[x].ta = t[x].tb = 0;
		}
	}

	void build(int x, int l, int r) {
		if(l == r) t[x] = meow(a[l], b[l], a[l] * b[l], a[l] * a[l]);
		else {
			build(lson); build(rson);
			t[x] = t[lc] + t[rc];
		}
	}

	void add(int x, int l, int r) {
		if(ql<=l && r<=qr) _add(x, l, r, s, w);
		else {
			pushdn(x, l, r);
			if(ql <= mid) add(lson);
			if(mid < qr ) add(rson);
			t[x] = t[lc] + t[rc];
		}
	}

	void cha(int x, int l, int r) {
		if(ql<=l && r<=qr) _set(x, l, r, s, w);
		else {
			pushdn(x, l, r);
			if(ql <= mid) cha(lson);
			if(mid < qr ) cha(rson);
			t[x] = t[lc] + t[rc];
		}
	}

	meow que(int x, int l, int r) {
		if(ql<=l && r<=qr) return t[x];
		else {
			pushdn(x, l, r);
			if(qr <= mid) return que(lson);
			else if(mid < ql ) return que(rson);
			else return que(lson) + que(rson);
		}
	}
	

	void Quer() {
		meow x = que(1, 1, n);
		double len = qr-ql+1, ans1 = x.c - x.a * x.b / len, ans2 = x.a2 - x.a * x.a / len;
		printf("%.10lf\n", ans1 / ans2);
	}
}
int main() {
	//freopen("in", "r", stdin);
	freopen("relative.in", "r", stdin);
	freopen("relative.out", "w", stdout);
	n=read(); Q=read();
	for(int i=1; i<=n; i++) a[i]=read();
	for(int i=1; i<=n; i++) b[i]=read();
	seg::build(1, 1, n);
	
	for(int i=1; i<=Q; i++) {
		op=read(); ql=read(); qr=read();
		if(op == 1) seg::Quer();
		if(op == 2) s=read(), w=read(), seg::add(1, 1, n);
		if(op == 3) s=read(), w=read(), seg::cha(1, 1, n);
	}
}

posted @ 2017-04-12 20:45  Candy?  阅读(591)  评论(0编辑  收藏  举报