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=l∑rsin(ai)
操作1:给出l,r,v,将al,al+1,...,ar分别加上v;
操作2:给出l,r,询问∑i=lrsin(ai)\sum\limits_{i=l}^{r}sin(a_i)i=l∑rsin(ai)
输入描述:
第一行一个整数n1
接下来一行n个整数表示a
,a2
,...,an
i
接下来一行一个整数m
接下来m行,每行表示一个操作,操作1表示为1 l r v,操作2表示为2 l r
保证1≤n,m,a
,v≤200000;1≤l≤r≤n,v是整数
输出描述:
对每个操作2,输出一行,表示答案,四舍五入保留一位小数
保证答案的绝对值大于0.1,且答案的准确值的小数点后第二位不是4或5
数据随机生成(n,m人工指定,其余整数在数据范围内均匀选取),并去除不满足条件的操作2
分析
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; } /*样例区 */ //------------------------------------------------------------