ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

蜂蜜柚子茶

2022-05-14 18:00:54  阅读:121  来源: 互联网

标签:10 撒糖 小戾 饮品 样例 柚子茶 半径 蜂蜜


题目描述

是从什么时候开始的呢···

大概是在「沽酒」的那一晚,小戾不声不响地给他们包厢上了多放了很多糖的蜂蜜柚子茶。

在自己被灌了不少酒之时,给向来嗜甜的自己。

小戾的面前放了\(N\)杯正常甜度的蜂蜜柚子茶,茶底都是早就做好的,是精心调配的比例。先前并没有往里添加糖的先例。

不过如果是给LCT的话,又有何不可。

小戾的「沽酒」设备先进,有批量给多杯饮品加糖的机器。说是加糖,其实就是撒糖。小戾在吧台上将N杯饮品排成一排,每次操作会以一个点为中心,在一个半径内给一些饮料添加糖。使用这种方式,总是位于中心的饮料被加的糖最多,而随着与中心的距离越来越远,饮品中被撒入的糖逐渐减少。具体来说,一次撒糖可以用三个参数来描述:\(x_i,r_i,w_i\),其中

\(x_i\):表示撒糖的中心。

\(r_i\):表示撒糖的半径。对于\(1≤j≤n\)的所有\(j\),当\(|j−x_i|≤r_i\)时,第\(j\)杯饮品中就会被撒入糖。注意,这并不代表\(x−r_i∈[1,n]\),机器撒糖当然有可能会将糖撒到杯子外面,我们不需要考虑这些撒出边界的糖。也就是说,当一杯饮品与撒糖中心之间的距离不超过撒糖半径ri时,这杯饮品就会被撒入糖。

wi:用于量化被撒到的糖。对于在该次撒糖半径中的饮品\(j\),即满足\(|j−x_i|≤r_i\)的某个\(j\),在该次撒糖过程中将会被撒到\(w_i−|j−x_i|\)单位的糖。也就是说,撒糖中心会被撒到wi单位的糖,每往左/右移一位,撒的糖数量就会减少一个单位。当然,被撒到糖的前提是位于撒糖半径内,在撒糖半径之外的饮品被撒入糖的量都是0。

小戾在撒的过程中也会做一些抽样,比如指定某一杯饮品,问它目前添加的糖有多少。

注意,初始时所有饮品都为正常糖量,可被认为是0单位添加糖。

输入格式
第一行两个数\(N,M\)。分别表示饮品的数量和操作的个数。

接下来M行,每行格式为下面的某一种:

+ \(x_i r_i w_i\):表示以xi为撒糖中心,\(r_i\)为撒糖半径,\(w_i\)为撒糖中心被撒到的糖量进行一次撒糖操作。

? \(x_i\):表示询问第\(x_i\)杯饮品的甜度。

保证\(1≤x_i,r_i≤n,0≤w_i≤10^9\)。保证\(r_i≤w_i\),即撒糖操作「撒」的糖必然是非负整数,不会「抽」糖。

输出格式
对于每个?输出一行表示答案。

样例输入1

3 5
+ 2 3 4
+ 1 1 2
+ 3 1 2
? 1
+ 1 2 8

样例输出1

5

样例输入2

10 5
+ 9 9 7
? 7
? 4
? 9
? 10

样例输出2

5
2
7
6

题目限制
时间限制:1000ms

空间限制:512MB

对于30%的数据,\(N,M≤10^3\)。

另有20%的数据,满足\(w_i≤10^4\)。

对于100%的数据,满足\(N,M≤2×10^5\)。 保证\(1≤x_i,r_i≤n,0≤w_i≤10^9,r_i≤w_i\)。

这道题其实第二个样例不符合题目要求,没过的可以尝试

区间加,单点求和,尝试用线段树解决。

首先如果区间加的是一个等差数列,其实也能用线段树做,但是太麻烦了,我们考虑用一些简单的方法解决。

对原数列进行差分后,我们可以发现,在某一段区间差分序列增加了1,后面又减少了1.

先通过半径求出撒糖的区间\(l\)和1\(r\),然后发现\(l+1\sim x\)的差分序列加了1,\(x+1\sim r\)这一段减少了1,同时按照题目给的公式求出\(l\)和\(r\)的增量\(x\)和\(y\),然后在l处差分序列增加\(x\),\(r+1\)处减少了y。

注意处理边界问题(n=1),询问x时输出\(1\sim x\)的和即可。

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5; 
int n,m,x,y,w,l,r;
char op;
struct node{
	long long sum,tag;
}tr[N<<2];
void pushdown(int o,int l,int r)
{
	int md=l+r>>1;
	tr[o<<1].tag+=tr[o].tag;
	tr[o<<1|1].tag+=tr[o].tag;
	tr[o<<1].sum+=tr[o].tag*(md-l+1);
	tr[o<<1|1].sum+=tr[o].tag*(r-md);
	tr[o].tag=0;
}
void update(int o,int l,int r,int x,int y,int z)
{
	if(x<=l&&r<=y)
	{
		tr[o].sum+=1LL*(r-l+1)*z;
		tr[o].tag+=z;
		return;
	}
	pushdown(o,l,r);
	int md=l+r>>1;
	if(md>=x)
		update(o<<1,l,md,x,y,z);
	if(md<y)
		update(o<<1|1,md+1,r,x,y,z);
	tr[o].sum=tr[o<<1].sum+tr[o<<1|1].sum;
}
long long query(int o,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
		return tr[o].sum;
	pushdown(o,l,r);
	int md=l+r>>1;
	long long ret=0;
	if(md>=x)
		ret+=query(o<<1,l,md,x,y);
	if(md<y)
		ret+=query(o<<1|1,md+1,r,x,y);
	return ret;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		scanf(" %c",&op);
		if(op=='?')
		{
			scanf("%d",&x);
			printf("%lld\n",query(1,1,n,1,x));
		}
		else
		{
			scanf("%d%d%d",&x,&y,&w);
			l=max(x-y,1),r=min(x+y,n);
			if(l!=r)
			{
				update(1,1,n,l,l,w-x+l);
				if(r<n)
					update(1,1,n,r+1,r+1,r-x-w);
				if(l<x)
				update(1,1,n,l+1,x,1);
				if(x<r)
					update(1,1,n,x+1,r,-1);
			}
			else
				update(1,1,n,x,x,w);
		}
	}
	return 0;
}

标签:10,撒糖,小戾,饮品,样例,柚子茶,半径,蜂蜜
来源: https://www.cnblogs.com/mekoszc/p/16270854.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有