luogu #6029. 「雅禮集訓 2017 Day1」市場
阿新 • • 發佈:2022-05-11
題面傳送門
看到區間除應該能自然想到勢能分析。
發現如果線段樹上一個區間原來的極差是\(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))); } }