题目链接
题目背景
从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落。
题目描述
有 n 个商贩,从 0 ~ n−1 编号,每个商贩的商品有一个价格 ai,有两种政令;同时,有一个外乡的旅客想要了解贸易市场的信息,有两种询问方式:
- (政令)l,r,c,对于 i∈[l,r],ai←ai+c
- (政令)l,r,d,对于 i∈[l,r],ai←⌊aid⌋
- (询问)给定 l,r,求 mini∈[l,r]ai
- (询问)给定 l,r,求 ∑i∈[l,r]ai
输入格式
第一行为两个空格隔开的整数 n,q,分别表示商贩个数和政令和询问个数。
第二行包含 n 个由空格隔开的整数 a0,a1,...,an−1
接下来 q 行,每行表示一个操作,第一个数表示操作编号 1 ~ 4,接下来的输入和问题描述一致。
输出格式
对于每个 3、4 操作,输出询问答案。
样例 #1
样例输入 #1
样例输出 #1
提示
【数据范围】
对于 30% 的数据,n,q≤103;
对于 60% 的数据,保证数据随机;
对于 100% 的数据,1≤n,q≤105,0≤l≤r≤n−1,c∈[−104,104],d∈[2,109]。
解题思路
势能线段树
同 势能线段树模板题二,由于 n−⌊nd⌋ 是一个增函数,记录线段树每个区间节点的最大值 mx 和最小值 mn,如果 mx−⌊mxd⌋=mn−⌊mnd⌋,说明该区间中每个数的值变化相等,对该区间节点打上懒标记,其他节点暴力递归即可
代码
#include <bits/stdc++.h>
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e5+5,inf=0x3f3f3f3f;
int n,m,a[N];
struct Tr
{
int l,r,add;
LL sum,mx,mn;
}tr[N<<2];
void pushup(int p)
{
tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
tr[p].mx=max(tr[p<<1].mx,tr[p<<1|1].mx);
tr[p].mn=min(tr[p<<1].mn,tr[p<<1|1].mn);
}
void pushdown(int p)
{
if(tr[p].add)
{
tr[p<<1].sum+=1ll*tr[p].add*(tr[p<<1].r-tr[p<<1].l+1);
tr[p<<1|1].sum+=1ll*tr[p].add*(tr[p<<1|1].r-tr[p<<1|1].l+1);
tr[p<<1].mx+=tr[p].add,tr[p<<1|1].mx+=tr[p].add;
tr[p<<1].mn+=tr[p].add,tr[p<<1|1].mn+=tr[p].add;
tr[p<<1].add+=tr[p].add,tr[p<<1|1].add+=tr[p].add;
tr[p].add=0;
}
}
void build(int p,int l,int r)
{
tr[p]={l,r};
if(l==r)
{
tr[p].sum=tr[p].mx=tr[p].mn=a[l];
return ;
}
int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
pushup(p);
}
void add(int p,int l,int r,int x)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
tr[p].sum+=x*(tr[p].r-tr[p].l+1);
tr[p].mx+=x,tr[p].mn+=x;
tr[p].add+=x;
return ;
}
pushdown(p);
int mid=tr[p].l+tr[p].r>>1;
if(l<=mid)add(p<<1,l,r,x);
if(r>mid)add(p<<1|1,l,r,x);
pushup(p);
}
void divide(int p,int l,int r,int d)
{
if(l<=tr[p].l&&tr[p].r<=r)
{
int dmx=tr[p].mx-(int)floor((double)tr[p].mx/d);
int dmn=tr[p].mn-(int)floor((double)tr[p].mn/d);
if(dmx==dmn)
{
tr[p].sum-=1ll*dmx*(tr[p].r-tr[p].l+1);
tr[p].mx-=dmx,tr[p].mn-=dmn;
tr[p].add-=dmx;
return ;
}
}
pushdown(p);
int mid=tr[p].l+tr[p].r>>1;
if(l<=mid)divide(p<<1,l,r,d);
if(r>mid)divide(p<<1|1,l,r,d);
pushup(p);
}
int ask_min(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r) return tr[p].mn;
pushdown(p);
int mid=tr[p].l+tr[p].r>>1;
int res=inf;
if(l<=mid)res=min(res,ask_min(p<<1,l,r));
if(r>mid)res=min(res,ask_min(p<<1|1,l,r));
return res;
}
LL ask_sum(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r) return tr[p].sum;
pushdown(p);
int mid=tr[p].l+tr[p].r>>1;
LL res=0;
if(l<=mid)res+=ask_sum(p<<1,l,r);
if(r>mid)res+=ask_sum(p<<1|1,l,r);
return res;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,1,n);
while(m--)
{
int op,l,r,x,d;
scanf("%d%d%d",&op,&l,&r);
l++,r++;
if(op==1)
{
scanf("%d",&x);
add(1,l,r,x);
}
else if(op==2)
{
scanf("%d",&d);
divide(1,l,r,d);
}
else if(op==3)
printf("%d\n",ask_min(1,l,r));
else
printf("%lld\n",ask_sum(1,l,r));
}
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2021-10-20 阶乘分解