1 /*
2 Source :wannafly 22 D 整数序列
3 Problem :给定长度为n的数组,有m次操作,op=1 时, 把a[l-r] 中的数加v, op=2时, 求sum(sin(a[l-r]))
4 Solution :由 sin(a+b) = sin(a)cos(b) + cos(a)*sin(b)
5 cos(a+b) = cos(a)cos(b) + sin(a)*sin(b)
6 可以维护区间的sin和以及cos和。
7 Date :2018-08-17-18.48
8 */
9
10 #include <bits/stdc++.h>
11 #include <cmath>
12 using namespace std;
13
14 typedef long long LL;
15 const int MAXN = 200005;
16 const LL MOD7 = 1e9+7;
17
18 int read()
19 {
20 int x=0;char ch=getchar();
21 while (ch<'0' || ch>'9') ch=getchar();
22 while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
23 return x;
24 }
25
26 struct Node
27 {
28 int l,r;
29 double c; //这里可能会爆int
30 double a; //sin
31 double b; //cos
32 };
33
34 struct SegTree
35 {
36 Node f[MAXN*8];
37 void pushUp(int t)
38 {
39 f[t].a=f[2*t].a+f[2*t+1].a;
40 f[t].b=f[2*t].b+f[2*t+1].b;
41 // f[t].g=f[2*t].g+f[2*t+1].g;
42 }
43
44 void pushDown(int t)
45 {
46 if (f[t].c>1e-9)
47 {
48 f[2*t].c+=f[t].c;
49 double cosv = cos(f[t].c); // 这里优化cos和sin的计算次数
50 double sinv = sin(f[t].c);
51 double tmp = f[2*t].a * cosv + f[2*t].b * sinv;
52 f[2*t].b = -f[2*t].a * sinv + f[2*t].b * cosv;
53 f[2*t].a = tmp;
54
55 f[2*t+1].c+=f[t].c;
56 tmp = f[2*t+1].a * cosv + f[2*t+1].b * sinv;
57 f[2*t+1].b = -f[2*t+1].a * sinv + f[2*t+1].b * cosv;
58 f[2*t+1].a = tmp;
59
60 f[t].c=0;
61 }
62 }
63
64 void build(int t,int l,int r, int *a)
65 {
66 f[t].l=l;
67 f[t].r=r;
68 f[t].c=0;
69 f[t].a=0;
70 f[t].b=0;
71 if (l==r)
72 {
73 f[t].a=sin(1.0*a[l]);
74 f[t].b=cos(1.0*a[l]);
75 return;
76 }
77 int mid=(l+r)/2;
78 build(2*t,l,mid,a);
79 build(2*t+1,mid+1,r,a);
80 pushUp(t);
81 }
82
83 void update(int t,int l,int r,int c)
84 {
85 // printf("update l=%d r=%d c=%d\n",l,r,c);
86 if (f[t].l==l && f[t].r==r)
87 {
88 f[t].c+=c;
89 double cosv = cos(c);
90 double sinv = sin(c);
91 double tmp = f[t].a * cosv + f[t].b * sinv;
92 f[t].b = -f[t].a * sinv + f[t].b * cosv;
93 f[t].a = tmp;
94 return ;
95 }
96 pushDown(t);
97 int mid=(f[t].l+f[t].r)/2;
98 if (r<=mid) update(2*t,l,r,c);
99 else if (l>mid) update(2*t+1, l,r, c);
100 else
101 {
102 update(2*t,l,mid,c);
103 update(2*t+1,mid+1,r,c);
104 }
105 pushUp(t);
106 }
107
108 double query(int t,int l,int r)
109 {
110 // printf("query t=%d l=%d r=%d\n",t,l,r);
111 if (f[t].l==l && f[t].r==r)
112 {
113 return f[t].a;
114 }
115 int mid=(f[t].l+f[t].r)/2;
116 pushDown(t);
117 double ans=0;
118 if (r<=mid) ans=query(2*t,l,r);
119 else if (l>mid) ans=query(2*t+1,l,r);
120 else ans=query(2*t,l,mid)+query(2*t+1,mid+1,r);
121 return ans;
122 }
123
124 void Debug(int t)
125 {
126 printf("************tree Node**********\n");
127 printf("\t l=%d r=%d \t\n", f[t].l, f[t].r);
128 printf("\t c=%d \t\n",f[t].c);
129 printf("\t a=%f \t\n",f[t].a);
130 printf("\t b=%f \t\n",f[t].b);
131 // printf("\t g=%f \t\n",f[t].g);
132 printf("************END NODE**********\n");
133 if (f[t].l==f[t].r) return;
134 Debug(2*t);
135 Debug(2*t+1);
136 }
137 }tree;
138
139 int a[MAXN];
140 int n,m;
141 int x;
142
143 int main()
144 {
145 // printf("round(-1.37)=%.1f\n", -1.37);
146 #ifndef ONLINE_JUDGE
147 freopen("test.txt","r",stdin);
148 #endif // ONLINE_JUDGE
149 n=read();
150 for (int i=1;i<=n;++i)
151 {
152 a[i]=read();
153 }
154 tree.build(1,1,n,a);
155 // tree.Debug(1);
156 m=read();
157 int op,l,r;
158 for (int i=1;i<=m;++i)
159 {
160 op=read();
161 l=read();
162 r=read();
163 // scanf("%d%d%d",&op,&l,&r);
164 // printf("op=%d l=%d r=%d\n",op,l,r);
165 if (op==1)
166 {
167 // scanf("%d",&x);
168 x=read();
169 tree.update(1,l,r,x);
170 // tree.Debug(1);
171 }
172 else
173 {
174 double tmp = tree.query(1, l, r);
175 printf("%.1f\n",tmp);
176 // tree.Debug(1);
177 }
178 }
179 return 0;
180 }