zoukankan      html  css  js  c++  java
  • [loj#2005][SDOI2017]相关分析 _线段树

    「SDOI2017」相关分析

    题目链接https://loj.ac/problem/2005


    题解

    把上面的式子拆掉,把下面的式子拆掉。

    发现所有的东西都能用线段树暴力维护。

    代码

    #include <bits/stdc++.h>
    
    #define N 100010 
    
    #define ls p << 1
    
    #define rs p << 1 | 1
    
    using namespace std;
    
    typedef double db;
    
    typedef double ll;
    
    ll sum[N << 2], tagx1[N << 2], tagx2[N << 2], tagy1[N << 2], tagy2[N << 2], sum2[N << 2];
    
    bool tag1[N << 2], tag2[N << 2];
    
    ll sumx[N << 2], sumy[N << 2];
    
    char *p1, *p2, buf[100000];
    
    #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
    
    int rd() {
    	int x = 0, f = 1;
    	char c = nc();
    	while (c < 48) {
    		if (c == '-')
    			f = -1;
    		c = nc();
    	}
    	while (c > 47) {
    		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
    	}
    	return x * f;
    }
    
    inline void pushup(int p) {
    	sum[p] = sum[ls] + sum[rs];
    	sumx[p] = sumx[ls] + sumx[rs];
    	sumy[p] = sumy[ls] + sumy[rs];
    	sum2[p] = sum2[ls] + sum2[rs];
    }
    
    void pls1(int l, int r, int s, int t, int p) {
    	int L = r - l + 1;
    	sum[p] += (ll)t * sumx[p] + (ll)s * sumy[p] + (ll)s * t * L;
    	sum2[p] += sumx[p] * s * 2 + (ll)s * s * L;
    	sumx[p] += (ll)s * L;
    	sumy[p] += (ll)t * L;
    	if (tag2[p]) {
    		tagx2[p] += s;
    		tagy2[p] += t;
    	}
    	else {
    		tagx1[p] += s;
    		tagy1[p] += t;
    		tag1[p] = true;
    	}
    }
    
    inline ll bfr2(int x) {
    	return (ll)x * (x + 1) * (2 * x + 1) / 6;
    }
    
    inline ll bfr1(int x) {
    	return (ll)x * (x + 1) / 2;
    }
    
    void pls2(int l, int r, int s, int t, int p) {
    	int L = r - l + 1;
    	sum[p] = bfr2(r) - bfr2(l - 1) + (ll)(s + t) * (bfr1(r) - bfr1(l - 1)) + (ll)L * s * t;
    	sum2[p] = bfr2(r) - bfr2(l - 1) + (ll)2 * s * (bfr1(r) - bfr1(l - 1)) + (ll)L * s * s;
    	sumx[p] = bfr1(r) - bfr1(l - 1) + (ll)L * s;
    	sumy[p] = bfr1(r) - bfr1(l - 1) + (ll)L * t;
    	tag1[p] = false;
    	tagx1[p] = tagy1[p] = 0;
    	tag2[p] = true;
    	tagx2[p] = s;
    	tagy2[p] = t;
    }
    
    inline void pushdown(int l, int r, int p) {
    	if (tag1[p]) {
    		int mid = (l + r) >> 1;
    		pls1(l, mid, tagx1[p], tagy1[p], ls);
    		pls1(mid + 1, r, tagx1[p], tagy1[p], rs);
    		tagx1[p] = tagy1[p] = 0;
    		tag1[p] = false;
    	}
    	if (tag2[p]) {
    		int mid = (l + r) >> 1;
    		pls2(l, mid, tagx2[p], tagy2[p], ls);
    		pls2(mid + 1, r, tagx2[p], tagy2[p], rs);
    		tagx2[p] = tagy2[p] = 0;
    		tag2[p] = false;
    	}
    }
    
    void update1(int x, int y, int s, int t, int l, int r, int p) {
    	if (x <= l && r <= y) {
    		pls1(l, r, s, t, p);
    		return;
    	}
    	int mid = (l + r) >> 1;
    	pushdown(l, r, p);
    	if (x <= mid) {
    		update1(x, y, s, t, l, mid, ls);
    	}
    	if (mid < y) {
    		update1(x, y, s, t, mid + 1, r, rs);
    	}
    	pushup(p);
    }
    
    void update2(int x, int y, int s, int t, int l, int r, int p) {
    	if (x <= l && r <= y) {
    		pls2(l, r, s, t, p);
    		return;
    	}
    	int mid = (l + r) >> 1;
    	pushdown(l, r, p);
    	if (x <= mid) {
    		update2(x, y, s, t, l, mid, ls);
    	}
    	if (mid < y) {
    		update2(x, y, s, t, mid + 1, r, rs);
    	}
    	pushup(p);
    }
    
    ll queryx1(int x, int y, int l, int r, int p) {
    	if (x <= l && r <= y) {
    		return sumx[p];
    	}
    	int mid = (l + r) >> 1;
    	ll ans = 0;
    	pushdown(l, r, p);
    	if (x <= mid) {
    		ans += queryx1(x, y, l, mid, ls);
    	}
    	if (mid < y) {
    		ans += queryx1(x, y, mid + 1, r, rs);
    	}
    	return ans;
    }
    
    ll queryy1(int x, int y, int l, int r, int p) {
    	if (x <= l && r <= y) {
    		return sumy[p];
    	}
    	int mid = (l + r) >> 1;
    	ll ans = 0;
    	pushdown(l, r, p);
    	if (x <= mid) {
    		ans += queryy1(x, y, l, mid, ls);
    	}
    	if (mid < y) {
    		ans += queryy1(x, y, mid + 1, r, rs);
    	}
    	return ans;
    }
    
    ll query(int x, int y, int l, int r, int p) {
    	if (x <= l && r <= y) {
    		return sum[p];
    	}
    	int mid = (l + r) >> 1;
    	ll ans = 0;
    	pushdown(l, r, p);
    	if (x <= mid) {
    		ans += query(x, y, l, mid, ls);
    	}
    	if (mid < y) {
    		ans += query(x, y, mid + 1, r, rs);
    	}
    	return ans;
    }
    
    ll query2(int x, int y, int l, int r, int p) {
    	if (x <= l && r <= y) {
    		return sum2[p];
    	}
    	int mid = (l + r) >> 1;
    	ll ans = 0;
    	pushdown(l, r, p);
    	if (x <= mid) {
    		ans += query2(x, y, l, mid, ls);
    	}
    	if (mid < y) {
    		ans += query2(x, y, mid + 1, r, rs);
    	}
    	return ans;
    }
    
    ll a1[N], a2[N];
    
    void build(int l, int r, int p) {
    	if (l == r) {
    		sum[p] = a1[l] * a2[l];
    		sum2[p] = a1[l] * a1[l];
    		sumx[p] = a1[l];
    		sumy[p] = a2[l];
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(l, mid, ls);
    	build(mid + 1, r, rs);
    	pushup(p);
    }
    
    int main() {
    	// freopen("gold.in", "r", stdin);
    	// freopen("gold.out", "w", stdout);
    	int n = rd(), Q = rd();
    	for (int i = 1; i <= n; i ++ ) {
    		a1[i] = rd();
    	}
    	for (int i = 1; i <= n; i ++ ) {
    		a2[i] = rd();
    	}
    	build(1, n, 1);
    	while (Q -- ) {
    		int opt = rd();
    		if (opt == 1) {
    			int l = rd(), r = rd();
    			db Up;
    			int L = r - l + 1;
    			Up = query(l, r, 1, n, 1);
    			Up -= (db)queryx1(l, r, 1, n, 1) * queryy1(l, r, 1, n, 1) / L;
    			db Down;
    			Down = query2(l, r, 1, n, 1);
    			Down -= (db)queryx1(l, r, 1, n, 1) * queryx1(l, r, 1, n, 1) / L;
    			printf("%.10lf
    ", Up / Down);
    		}
    		else if (opt == 2) {
    			int l = rd(), r = rd(), s = rd(), t = rd();
    			update1(l, r, s, t, 1, n, 1);
    		}
    		else {
    			int l = rd(), r = rd(), s = rd(), t = rd();
    			update2(l, r, s, t, 1, n, 1);
    		}
    	}
    	return 0;
    }
    

    小结:对拍的时候要记得,数据尽量和题面吻合,不然容易出一些奇奇怪怪的错误。比如说这个题考试的时候,我就有个值忘记开$long long$,对拍没拍出来因为我保证数据非常小。

  • 相关阅读:
    Oracle 分区表管理之组合分区(分区索引失效与性能比较以及12.2c分区表新特性)
    博客搬家了
    Java中文件操作
    Java中的LinkedList介绍
    Android数据缓存
    Android QQ空间浏览图片动画特效的实现(※)
    关于android中线性布局的layout_gravity属性
    Android中AutoCompleteTextView的使用
    Android中GridView使用总结
    Android实现自适应正方形GridView(陌陌引导页面效果)
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11421275.html
Copyright © 2011-2022 走看看