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

    Problem

    维护一个序列(a),每次操作有两种类型:

    • 1 l r v(a_l sim a_r)的所有数加(v)
    • 2 l r(sum_{i = l} ^ r sin (a_i))
      输入数据均小于(2 imes 10^5)

    Solution

    上午刚做完一个Ynoi,以为是最简单的Ynoi题了,结果这题更是重量级。
    不难发现通过两个诱导公式可以做:

    [sin(alpha + eta) = sin(alpha) cos(eta) + sin(eta)cos(alpha)\ cos(alpha + eta) = cos(alpha) cos(eta) - sin(alpha) sin(eta) ]

    然后用线段树,节点维护sin,cos和即可。

    # include <bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 5;
    int n;
    double a[N];
    int m;
    struct node
    {
        double Sin,Cos,lazy;
    }T[N << 2];
    void pushup(int root)
    {
    
        T[root].Sin = T[root << 1].Sin + T[root << 1 | 1].Sin;
        T[root].Cos = T[root << 1].Cos + T[root << 1 | 1].Cos;
        return;
    }
    void build(int root,int l,int r)
    {
        if(l == r)
        {
            T[root].Sin = sin(a[l]),T[root].Cos = cos(a[l]);
            T[root].lazy = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1,l,mid),build(root << 1 | 1, mid + 1, r);
        pushup(root);
        return;
    }
    void pushdown(int root)
    {
        if(T[root].lazy == 0) return;
        double tag = T[root].lazy;
        double sine = sin(tag),cosine = cos(tag);
        double sn = T[root << 1].Sin,cs = T[root << 1].Cos;
        T[root << 1].Sin = sn * cosine + sine * cs;
        T[root << 1].Cos = cosine * cs - sine * sn;
        sn = T[root << 1 | 1].Sin,cs = T[root << 1 | 1].Cos;
        T[root << 1 | 1].Sin = sn * cosine + sine * cs;
        T[root << 1 | 1].Cos = cosine * cs - sine * sn;
        T[root << 1].lazy += tag,T[root << 1 | 1].lazy += tag;
        T[root].lazy = 0;
        return;
    }
    void update(int root,int l,int r,int s,int t,double d)
    {
        if(l <= s && t <= r)
        {
            double sine = sin(d),cosine = cos(d);
            double sn = T[root].Sin,cs = T[root].Cos;
            T[root].Sin = sn * cosine + sine * cs;
            T[root].Cos = cosine * cs - sine * sn;
            T[root].lazy += d;
            return;
        }
        pushdown(root);
        int mid = (s + t) >> 1;
        if(l <= mid) update(root << 1,l,r,s,mid,d);
        if(r > mid) update(root << 1 | 1,l,r,mid + 1,t,d);
        pushup(root);
        return;
    }
    double query(int root,int l,int r,int s,int t)
    {
        if(l <= s && t <= r) return T[root].Sin;
        pushdown(root);
        int mid = (s + t) >> 1;
        double ans = 0;
        if(l <= mid) ans = ans + query(root << 1,l,r,s,mid);
        if(r > mid) ans = ans + query(root << 1 | 1,l,r,mid + 1,t);
        return ans;
    }
    int main(void)
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++) scanf("%lf",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        while(m--)
        {
            int opt,l,r;
            scanf("%d%d%d",&opt,&l,&r);
            if(opt == 1)
            {
                double v; scanf("%lf",&v);
                update(1,l,r,1,n,v);
            }
            else 
            {
                printf("%.1lf
    ",query(1,l,r,1,n));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    FFmpeg解码H264及swscale缩放详解
    linux中cat more less head tail 命令区别
    C语言字符串操作总结大全(超详细)
    如何使用eclipse进行嵌入式Linux的开发
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/15187426.html
Copyright © 2011-2022 走看看