1 1 2 1 1 5 4 1 1 7 1 3 17 3 2 4 2 1 5
0 22题意:给出 n(1 ~ 100000),m (1 ~ 100000) ,代表存在一个初始化为 0 ,数量为 n 的数列,后给出 m 个操作。
1 a b,代表将数列中第 k 个数增加 b( -2 ^ 31 <= b <= 2 ^ 31);
2 a b,代表输出数列 a 到 b 的总和;
3 a b,代表将数列 l 到 r 区间的数更改成最近的斐波那契数。
输出所有 2 操作的结果。
表示是单点更新……但是我们可以知道其实每次要更新的节点就是那些不是斐波那契数的……如果我们能维护出a到b哪些点是需要更新的这样更新的复杂度就降下来了——这个地方可以用map……#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> using namespace std; long long fib[] ={1LL,1LL,2LL,3LL,5LL,8LL,13LL,21LL,34LL,55LL, 89LL,144LL,233LL,377LL,610LL,987LL,1597LL,2584LL,4181LL,6765LL, 10946LL,17711LL,28657LL,46368LL,75025LL,121393LL,196418LL,317811LL,514229LL,832040LL, 1346269LL,2178309LL,3524578LL,5702887LL,9227465LL,14930352LL,24157817LL,39088169LL,63245986LL,102334155LL, 165580141LL,267914296LL,433494437LL,701408733LL,1134903170LL,1836311903LL,2971215073LL,4807526976LL,7778742049LL,12586269025LL, 20365011074LL,32951280099LL,53316291173LL,86267571272LL,139583862445LL,225851433717LL,365435296162LL,591286729879LL,956722026041LL,1548008755920LL, 2504730781961LL,4052739537881LL,6557470319842LL,10610209857723LL,17167680177565LL,27777890035288LL,44945570212853LL,72723460248141LL,117669030460994LL,190392490709135LL, 308061521170129LL,498454011879264LL,806515533049393LL,1304969544928657LL,2111485077978050LL,3416454622906707LL,5527939700884757LL,8944394323791464LL,14472334024676221LL,23416728348467685LL, 37889062373143906LL,61305790721611591LL,99194853094755497LL,160500643816367088LL,259695496911122585LL,420196140727489673LL,679891637638612258LL,1100087778366101931LL,1779979416004714189LL,2880067194370816120LL, 4660046610375530309LL,7540113804746346429LL }; long long tree[100000 * 4 + 17]; long long a[100017]; int n, m; map <long long, long long> changes; void add(int p, int l, int r, long long x,long long num) { if (l == r){tree[p] += num; return;} int mid = (l + r) / 2; if (x <= mid) add(p * 2, l, mid, x, num); else add(p * 2 + 1, mid + 1, r, x, num); tree[p] = tree[p * 2] + tree[p * 2 + 1]; } long long find(int p, int l, int r, int x, int y) { if (x <= l && r <= y)return tree[p]; int mid = (l + r) / 2; if (y <= mid) return find(p * 2, l, mid, x, y); if (x > mid) return find(p * 2 + 1, mid + 1, r, x, y); return (find (p * 2, l, mid, x, mid) + find(p * 2 + 1, mid + 1, r, mid + 1, y)); } long long near(long long t) { int p = lower_bound(fib, fib + 92, t) - fib; if(p==0) return fib[p]; if(fib[p]-t>=t-fib[p-1]) p--; return fib[p]; } int main() { while (scanf("%d%d", &n, &m) != EOF) { memset(tree, 0, sizeof(tree)); memset(a, 0, sizeof(a)); changes.clear(); for (int i = 1; i <= n; i++) changes.insert(pair<long long, long long>(i, 1)); for (int i = 1; i <= m; i++) { int x, y, z; scanf("%d%d%d", &x, &y, &z); if (x == 1) { add(1, 1, n, y, z); a[y] += z; long long tmp = near(a[y]); if(tmp != a[y]) changes[y] = tmp - a[y]; } if (x == 2) { //for (int j = 1; j <= 4 * n; j++) //cout << tree[j] << ' '; cout << find(1, 1, n, y, z) << endl; } if (x == 3) { map<long long, long long>::iterator t1, t2; t1 = changes.lower_bound(y); t2 = changes.upper_bound(z); for ( map<long long, long long>::iterator p = t1; p != t2; p++) { a[p->first] += p->second; add(1, 1, n, p->first, p->second); } changes.erase(t1, t2); } } } return 0; }