1. 程式人生 > 其它 >luogu #6029. 「雅禮集訓 2017 Day1」市場

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