O - 卿学姐种美丽的花
给一个区间,等差数列更新,单点查询
我们可以开一个线段树记录这个点被更新的次数,然后因为是区间更新,所以我们需要一个lazy,lazy表示这个区间的被更新的数列的首项是多少,还有一个cnt,表示公差,因为两个数列加和到一起时,公差也会相加,所以就是这样了,然后lazy下放的时候,也是计算下两个子区间的首端点的位置是多少,相当于把这个数列分为两个子数列
然后我们就可以发现,叶子节点的lazy就是这个点被更新的数,然后再加上叶子节点初始的值,就是更新后的值啦,然后就可以了,因为N是1e6,线段树5W+KB的内存就卡过去了,哦,对,还有最后那个取模,因为答案不会爆long long,所以long long存,最后输出的时候模(膜)一下就行。
另:题解貌似给的是树状数组
代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> using namespace std; #define mod 772235 #define ll long long #define maxn 1000005 #define lid (id<<1) #define rid ((id<<1)|1) long long a[maxn]; int N, Q; struct segtree { int l, r; //long long sum; ll lazy, cnt; }tr[maxn * 4]; void bulid(int id, int l, int r) { tr[id].l = l; tr[id].r = r; if (l == r) { return; } int mid = (l + r) >> 1; bulid(lid, l, mid); bulid(rid, mid + 1, r); //tr[id].sum = tr[lid].sum + tr[rid].sum; } void push_down(int id) { if (tr[id].lazy != 0) { //printf("push_down id %d ", id); tr[lid].cnt += tr[id].cnt, tr[rid].cnt += tr[id].cnt; int mid = tr[lid].r; ll v = tr[id].lazy; //printf("%lld ", v); //tr[lid].sum += (ll)(2 * v - (tr[lid].r - tr[lid].l)*tr[lid].cnt)*(ll)(tr[lid].r - tr[lid].l + 1) / 2; tr[lid].lazy += v; v = tr[id].lazy - (mid + 1 - tr[id].l)*tr[id].cnt; //printf("%lld\n", v); //tr[rid].sum += (ll)(2 * v - (tr[rid].r - tr[rid].l)*tr[rid].cnt)*(ll)(tr[rid].r - tr[rid].l + 1) / 2; tr[rid].lazy += v; tr[id].lazy = 0; //printf("cnt %lld cnt %lld\n", tr[lid].cnt, tr[rid].cnt); tr[id].cnt = 0; } } void update(int id, int l, int r, long long v) { if (l == tr[id].l&&tr[id].r == r) { tr[id].lazy += v; tr[id].cnt++; //tr[id].sum += (ll)(2 * v - (r - l)*tr[id].cnt)*(ll)(r - l + 1) / 2; return; } push_down(id); int mid = (tr[id].l + tr[id].r) >> 1; if (r <= mid) update(lid, l, r, v); else if (l > mid) update(rid, l, r, v); else { update(lid, l, mid, v); update(rid, mid + 1, r, v - (mid + 1 - l)); } //tr[id].sum = tr[lid].sum + tr[rid].sum; } long long query(int id, int l, int r) { if (l == tr[id].l&&r == tr[id].r) return tr[id].lazy; push_down(id); int mid = (tr[id].l + tr[id].r) >> 1; if (r <= mid) return query(lid, l, r); else if (l > mid) return query(rid, l, r); else return query(lid, l, mid) + query(rid, mid + 1, r); } int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); scanf("%d%d", &N, &Q); for (int i = 1; i <= N; ++i) scanf("%lld", &a[i]); bulid(1, 1, N); /*for (int j = 1; j <= 30; ++j) printf("%d %d %d %lld %lld\n", j, tr[j].l, tr[j].r, tr[j].lazy, tr[j].cnt); printf("\n");*/ int f, x, y, l, r; ll ans; for (int i = 0; i < Q; ++i) { scanf("%d", &f); if (f == 1) { scanf("%d%d", &x, &y); l = x; r = min(x + y - 1, N); update(1, l, r, y); //printf("update %d %d %d\n", l, r, y); } else if (f == 2) { scanf("%d", &x); ans = (query(1, x, x)+a[x]) % mod; printf("%lld\n", ans); } /*for (int j = 1; j <= 30; ++j) printf("%d %d %d %lld %lld\n", j, tr[j].l, tr[j].r, tr[j].lazy, tr[j].cnt); printf("\n");*/ } /*for (int j = 1; j <= 30; ++j) printf("%d %d %d %lld %lld\n", j, tr[j].l, tr[j].r, tr[j].lazy, tr[j].cnt); printf("\n");*/ //system("pause"); //while (1); return 0; }