2016 UESTC Training for Data Structures O - 卿学姐种美丽的花 CDOJ 1344 线段树/树状数组

O - 卿学姐种美丽的花

给一个区间,等差数列更新,单点查询

我们可以开一个线段树记录这个点被更新的次数,然后因为是区间更新,所以我们需要一个lazylazy表示这个区间的被更新的数列的首项是多少,还有一个cnt,表示公差,因为两个数列加和到一起时,公差也会相加,所以就是这样了,然后lazy下放的时候,也是计算下两个子区间的首端点的位置是多少,相当于把这个数列分为两个子数列

然后我们就可以发现,叶子节点的lazy就是这个点被更新的数,然后再加上叶子节点初始的值,就是更新后的值啦,然后就可以了,因为N1e6,线段树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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值