zoukankan      html  css  js  c++  java
  • 洛谷 P6327 区间加区间sin和

    Description

    洛谷传送门

    似乎是一道前 (Ynoi),不过反正现在不是了。

    Solution

    题目名字已经暗示我们要使用线段树之类的数据结构了。

    看一眼题面,好吧,就是线段树维护。

    本题需要一点数学基础。

    [sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b) ]

    [cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b) ]

    所以,我们需要维护一下区间 (sin) 和,同时也要维护一下区间 (cos) 和。

    然后就没什么了,注意这道题还卡精度。

    在区间加 (k) 时,要把 (sin(k))(cos(k)) 提前存下来,不能每次都计算一遍,不然会被卡。

    我是不会告诉你,我因为不知道怎么计算 sin 看了一个晚上,后来一看题解发现有函数……

    Code

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #define ls rt << 1
    #define rs rt << 1 | 1
    #define ll long long
    
    using namespace std;
    
    template <typename T> inline void read(T &x){
    	x = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') ch = getchar();
    	while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    }
    
    const int N = 2e5 + 10;
    int n, m;
    int a[N];
    double ssin[N << 2], scos[N << 2];
    ll lazy[N << 2];
    double sink, cosk;
    
    inline void pushup(int rt){
    	ssin[rt] = ssin[ls] + ssin[rs];
    	scos[rt] = scos[ls] + scos[rs];
    }
    
    inline void add(int a, double sinb, double cosb){
    	double sina = ssin[a], cosa = scos[a];
    	ssin[a] = sina * cosb + cosa * sinb;
    	scos[a] = cosa * cosb - sina * sinb;
    }
    
    inline void pushdown(int rt){
    	if(lazy[rt]){
    		double sinb = sin(lazy[rt]), cosb = cos(lazy[rt]);
    		add(ls, sinb, cosb);
    		add(rs, sinb, cosb);
    		lazy[ls] += lazy[rt], lazy[rs] += lazy[rt];
    		lazy[rt] = 0;
    	}
    }
    
    inline void build(int l, int r, int rt){
    	if(l == r){
    		ssin[rt] = sin(a[l]);
    		scos[rt] = cos(a[l]);
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(l, mid, ls);
    	build(mid + 1, r, rs);
    	pushup(rt);
    }
    
    inline void update(int L, int R, int k, int l, int r, int rt){
    	if(L <= l && r <= R){
    		add(rt, sink, cosk);
    		lazy[rt] += k;
    		return;
    	}
    	pushdown(rt);
    	int mid = (l + r) >> 1;
    	if(L <= mid) update(L, R, k, l, mid, ls);
    	if(R > mid) update(L, R, k, mid + 1, r, rs);
    	pushup(rt);
    }
    
    inline double query(int L, int R, int l, int r, int rt){
    	if(L <= l && r <= R)
    		return ssin[rt];
    	pushdown(rt);
    	int mid = (l + r) >> 1;
    	double res = 0;
    	if(L <= mid) res += query(L, R, l, mid, ls);
    	if(R > mid) res += query(L, R, mid + 1, r, rs);
    	return res;
    }
    
    int main(){
    	read(n);
    	for(int i = 1; i <= n; i++)
    		read(a[i]);
    	build(1, n, 1);
    	read(m);
    	for(int i = 1; i <= m; i++){
    		int op, l, r, k;
    		read(op), read(l), read(r);
    		if(op == 1){
    			read(k);
    			sink = sin(k), cosk = cos(k);
    			update(l, r, k, 1, n, 1);
    		}else printf("%.1lf
    ", query(l, r, 1, n, 1));
    	}
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15411772.html

  • 相关阅读:
    人生感悟:人与人之间的距离
    9月22日测试题目
    Java自学第五十二天
    Java自学第五十一天
    Java自学第五十天
    Java自学第四十九天
    Java自学第四十八天
    Java自学第四十七天
    Java自学第四十六天
    Java自学第四十五天
  • 原文地址:https://www.cnblogs.com/xixike/p/15411772.html
Copyright © 2011-2022 走看看