1015 整数序列 线段树 正弦余弦懒标记

 链接:https://ac.nowcoder.com/acm/contest/26896/1015
来源:牛客网

题目描述

给出一个长度为n的整数序列a1,a2,...,an,进行m次操作,操作分为两类。
操作1:给出l,r,v,将al,al+1,...,ar分别加上v;
操作2:给出l,r,询问∑i=lrsin(ai)\sum\limits_{i=l}^{r}sin(a_i)i=lrsin(ai)

输入描述:

第一行一个整数n
接下来一行n个整数表示a
1
,a
2
,...,a
n

接下来一行一个整数m
接下来m行,每行表示一个操作,操作1表示为1 l r v,操作2表示为2 l r
保证1≤n,m,a
i
,v≤200000;1≤l≤r≤n,v是整数

输出描述:

对每个操作2,输出一行,表示答案,四舍五入保留一位小数
保证答案的绝对值大于0.1,且答案的准确值的小数点后第二位不是4或5
数据随机生成(n,m人工指定,其余整数在数据范围内均匀选取),并去除不满足条件的操作2
示例1

输入

复制
4
1 2 3 4
5
2 2 4
1 1 3 1
2 2 4
1 2 4 2
2 1 3

输出

复制
0.3
-1.4
-0.3

分析

cos[x + add] = cosx * cos[add] - sinx * sin[add];

其中cos[add]和 sin[add]是常数,所以用线段树维护区间的cosx 和 sinx 总和就可以了

//-------------------------代码----------------------------

//#define int ll
const int N = 2e5+10;
int n,m;
int a[N];
struct node {
    int l,r;
    double ssum,csum;
    ll add;
} tr[N<<2];

void push_up(int u) {
    tr[u].csum = tr[u << 1].csum + tr[u << 1 | 1].csum;
    tr[u].ssum = tr[u << 1].ssum + tr[u << 1 | 1].ssum;
}

void eval(node &u,ll add) {
    double csum = u.csum, ssum = u.ssum;
    double cosadd = cos(add), sinadd = sin(add);
    u.ssum = cosadd * ssum + sinadd * csum;
    u.csum = cosadd * csum - sinadd * ssum;
    u.add += add;
}

void push_down(int u) {
    auto &root = tr[u],&left = tr[ul],&right = tr[ur];
    if(root.add) {
        eval(left,root.add);
        eval(right,root.add);
        root.add = 0;
    }
}

void build(int u,int l,int r) {
    tr[u].l = l, tr[u].r = r;

    if (l == r)
    {
        tr[u].csum = cos(a[l]);
        tr[u].ssum = sin(a[l]);
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid);
    build(u << 1 | 1, mid + 1, r);
    push_up(u);
}

void modify(int u,int l,int r,int v) {
    if (tr[u].l >= l && tr[u].r <= r)
    {
        eval(tr[u], v);
        return;
    }
    push_down(u);
    int mid = tr[u].l + tr[u].r >> 1;
    if (l <= mid)
        modify(u << 1, l, r, v);
    if (r > mid)
        modify(u << 1 | 1, l, r, v);
    push_up(u);
}

double query(int u,int l,int r) {
    if(l <= tr[u].l && tr[u].r <= r) {
        return tr[u].ssum;
    }
    if(l > tr[u].r || r < tr[u].l) return 0;
    push_down(u);
    return query(ul,l,r) + query(ur,l,r);
}

void solve()
{
//    cin>>n>>m;
    cin>>n;
    fo(i,1,n) cin>>a[i];
    build(1,1,n);
    cin>>m;
    while(m -- ) {
        int op,l,r;
        cin>>op>>l>>r;
        if(op == 1) {
            int x;cin>>x;
            modify(1,l,r,x);
        } else { 
           cout<<fixed<<setprecision(1)<<query(1,l,r)<<endl;
        }
    }
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

posted @ 2022-08-10 00:04  er007  阅读(31)  评论(0)    收藏  举报