牛客网wannafly22 D 整数序列
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 }