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;
}