余弦
Description
給定長度為 ? 的實數序列 ??(1 ≤ ? ≤ ?), 你需要在數列上進行兩類操作:
1. 把 ? ≤ ? ≤ ? 中的每個 ?? 加上實數 ?。
2. 求 ? ≤ ? ≤ ? 中 cos(??) 的和。?
Input
輸入包含多組數據,最開頭的正整數 T (T≤ 5) 指明了數據組數。
對于每組數據:第一行 2 個整數 N、M,表示數列長度與操作個數。
第二行 N 個實數 ??(|??| ≤ 100),小數點后最多有 3 位小數。
接下來 M 行每行形如“1 ? ? ?” 或 “2 ? ?”。
前者表示一個第 1 類操作,后者表示一個第 2 類操作。
其中 ?, ?(1 ≤ ? ≤ ? ≤ ?) 是整數,而?(|?| ≤ 100)是實數,小數點后最多有 3位小數。?
Output
對于每組數據,先輸出一行 "Case #k:",其中 k 是該組數據的編號,從 1 開始。
對于每組數據中的每個第 2 類操作,輸出一個實數表示答案,保留 3 位小數。
Sample Input 1
3 3 3 0 -2 -6 1 1 2 -7 2 1 2 2 2 3 5 4 4 2 4 -0 -4 1 1 4 2 2 4 5 1 3 5 5 2 2 3 7 3 0.123 -19.002 -57.507 34.434 -80.886 -17.115 69.843 2 2 7 1 2 7 16.341 2 1 3
Sample Output 1
Case #1: -0.157 0.049 Case #2: -1.070 -0.649 Case #3: 1.854 -0.842
Hint
對于 20%的數據,1 ≤ N, M ≤ 1000。
對于另外 20%的數據,沒有 1 類操作。
對于另外 20%的數據,1 類操作均在 2 類操作之前。
對于 100%的數據,1 ≤ N, M ≤ 200000。
?
(我不會說我因為傳參寫錯了而調了一晚上的);
其實是水題;
你在每個節點維護sin值的和還有cos值的和;
你加一個數, 根據高一的知識,∑cos(ai+c)=∑(cosai*cosc-sinai*sinc);
而上面的式子可以化簡為∑cos(ai+c)= cosc∑cosai - sincΣsinai , 顯然可以快速合并;
合并sin值同理;
代碼奉上:
//By zZhBr #include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std;inline int read() {int res=0;bool flag=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')flag=1;ch=getchar();}while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch-'0');ch=getchar();}return flag?-res:res; } const int N = 200010; const double eps = 1e-9;int n, m, T; double a[N]; int cnt = 1;struct SegmentTree {int l, r;double sinn, coss;double flag;void clean(){l = r = 0;sinn = coss = 0;flag = 0;} }t[N<<2]; #define ls(x) x << 1 #define rs(x) x << 1 | 1inline void pushup(int o) {t[o].sinn = t[ls(o)].sinn + t[rs(o)].sinn;t[o].coss = t[ls(o)].coss + t[rs(o)].coss;t[o].l = t[ls(o)].l, t[o].r = t[rs(o)].r; }inline void build(int l, int r, int o) {if (l == r){t[o].l = t[o].r = l;t[o].sinn = sin(a[l]);t[o].coss = cos(a[l]);t[o].flag = 0.0;return;}int mid = l + r >> 1;build(l, mid, o<<1);build(mid + 1, r, o<<1|1);pushup(o); }inline void spread(int o) {if (t[o].flag == 0) return;double c = t[o].flag;double X = t[ls(o)].coss, Y = t[ls(o)].sinn;t[ls(o)].coss = cos(c) * X - sin(c) * Y;t[ls(o)].sinn = sin(c) * X + cos(c) * Y;X = t[rs(o)].coss, Y = t[rs(o)].sinn;t[rs(o)].coss = cos(c) * X - sin(c) * Y;t[rs(o)].sinn = sin(c) * X + cos(c) * Y;t[ls(o)].flag += c;t[rs(o)].flag += c;t[o].flag = 0;}inline void change(int li, int ri, int o, double v) {if (li <= t[o].l and ri >= t[o].r){double la=t[o].coss;t[o].coss = cos(v) * t[o].coss - sin(v) * t[o].sinn;t[o].sinn = sin(v) * la + cos(v) * t[o].sinn;t[o].flag += v;return;}spread(o);int mid = t[o].l + t[o].r >> 1;if (li <= mid) change(li, ri,ls(o), v);if (ri > mid) change(li, ri, rs(o), v);pushup(o); }inline double query(int o, int li, int ri) {if (li <= t[o].l and ri >= t[o].r){return t[o].coss;}spread(o);double res = 0;int mid = t[o].l + t[o].r >> 1;if (li <= mid) res += query(ls(o), li, ri);if (ri > mid) res += query(rs(o), li, ri);return res; }inline void init(int x) {cnt = 1;for (register int i = 1 ; i <= x ; i ++){t[i].clean();} }int main() {T = read();for (register int tiime = 1 ; tiime <= T ; tiime++){printf("Case #%d:\n", tiime); n = read(), m = read(); init(n<<2);for (register int i = 1 ; i <= n ; i ++) cin >> a[i];build(1, n, 1);while (m--){int opt = read();if (opt == 1){int x = read(), y = read();double v;cin >> v;change(x, y, 1, v);}if (opt == 2){int x = read(), y = read();printf("%.3lf\n", query(1, x, y));}}init(n<<1);} }
?
?
?
轉載于:https://www.cnblogs.com/BriMon/p/9113756.html
總結
- 上一篇: 足金一克多少钱啊?
- 下一篇: python3:利用SMTP协议发送QQ