luogu #6029. 「雅礼集训 2017 Day1」市场
题面传送门
看到区间除应该能自然想到势能分析。
发现如果线段树上一个区间原来的极差是\(P\),那么一次暴力递归以后极差会变成\(O(\frac{P}{d})\)级别的东西,每次修改操作影响的只有\(O(\log n)\)个区间,所以暴力递归直到全区间相等的复杂度是\(O(n\log n\log W)\)的。
但是你写了一发交上去60pts。
发现极差是\(1\)的时候有一种特殊情况,就是最小值是\(kd-1\),最大值是\(kd\),那么除了\(d\)之后极差还是\(1\),然后反复加除几次就咕咕了。
但是这种情况实际上也是可以转化为区间减的,然后就可以做到严格\(O(n\log n\log W)\)了。
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (100000+5)
#define M (1000000+5)
#define K (20+5)
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;
int n,m,k,op,x,y,z,A[N];
namespace Tree{
#define ls now<<1
#define rs now<<1|1
ll S[N<<2];int Si[N<<2],G[N<<2],Mx[N<<2],Mi[N<<2];I void PF(int now,int w){G[now]+=w;S[now]+=1ll*Si[now]*w;Mx[now]+=w;Mi[now]+=w;}I void P(int now){G[now]&&(PF(ls,G[now]),PF(rs,G[now]),G[now]=0);}
I void Up(int now){S[now]=S[ls]+S[rs];Mx[now]=max(Mx[ls],Mx[rs]);Mi[now]=min(Mi[ls],Mi[rs]);}I void BD(int l=0,int r=n-1,int now=1){Si[now]=r-l+1;if(l==r) {S[now]=Mx[now]=Mi[now]=A[l];return;}int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);Up(now);}
I void I1(int x,int y,int z,int l=0,int r=n-1,int now=1){if(x<=l&&r<=y) return PF(now,z);int m=l+r>>1;P(now);x<=m&&(I1(x,y,z,l,m,ls),0);y>m&&(I1(x,y,z,m+1,r,rs),0);Up(now);}
I void I2(int x,int y,int z,int l=0,int r=n-1,int now=1){if(x<=l&&r<=y){if(Mx[now]/z-(Mx[now]<0&&Mx[now]%z)-Mx[now]==Mi[now]/z-(Mi[now]<0&&Mi[now]%z)-Mi[now]) return PF(now,Mx[now]/z-(Mx[now]<0&&Mx[now]%z)-Mx[now]);}int m=l+r>>1;P(now);x<=m&&(I2(x,y,z,l,m,ls),0);y>m&&(I2(x,y,z,m+1,r,rs),0);Up(now);}
I ll Q1(int x,int y,int l=0,int r=n-1,int now=1){if(x<=l&&r<=y) return S[now];int m=l+r>>1;P(now);ll Fs=0;x<=m&&(Fs+=Q1(x,y,l,m,ls));y>m&&(Fs+=Q1(x,y,m+1,r,rs));return Fs;}
I int Q2(int x,int y,int l=0,int r=n-1,int now=1){if(x<=l&&r<=y) return Mi[now];int m=l+r>>1,F1=2e9,F2=2e9;P(now);x<=m&&(F1=Q2(x,y,l,m,ls));y>m&&(F2=Q2(x,y,m+1,r,rs));return min(F1,F2);}
#undef ls
#undef rs
}
int main(){
freopen("1.in","r",stdin);
int i,j;scanf("%d%d",&n,&m);for(i=0;i<n;i++) scanf("%d",&A[i]);Tree::BD();while(m--){
scanf("%d%d%d",&op,&x,&y);op<=2?(scanf("%d",&z),op^2?Tree::I1(x,y,z):Tree::I2(x,y,z),0):(op^3?printf("%lld\n",Tree::Q1(x,y)):printf("%d\n",Tree::Q2(x,y)));
}
}