数据结构:分块-区间加法和查询前驱(比其小的最大元素)
刚才是查询比指定的数x小的数有多少个
这里是查询比指定的数x小的最大的那个数是啥
其实只要把块内查询的二分稍作修改即可
在块内维护其它结构使其更具有拓展性,比如放一个 set ,这样如果还有插入、删除元素的操作,会更加的方便
1 #include<cstdio> 2 #include<cmath> 3 #include<set> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=100005; 7 int n,blo; 8 int v[maxn],bl[maxn],atag[maxn]; 9 set<int> st[105]; 10 inline long long read() 11 { 12 long long x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 void add(int a,int b,int c) 18 { 19 for(int i=a;i<=min(bl[a]*blo,b);i++) 20 { 21 st[bl[a]].erase(v[i]); 22 v[i]+=c; 23 st[bl[a]].insert(v[i]); 24 } 25 if(bl[a]!=bl[b]) 26 { 27 for(int i=(bl[b]-1)*blo+1;i<=b;i++) 28 { 29 st[bl[b]].erase(v[i]); 30 v[i]+=c; 31 st[bl[b]].insert(v[i]); 32 } 33 } 34 for(int i=bl[a]+1;i<=bl[b]-1;i++) atag[i]+=c; 35 } 36 int query(int a,int b,int c) 37 { 38 int ans=-1; 39 for(int i=a;i<=min(bl[a]*blo,b);i++) 40 { 41 int val=v[i]+atag[bl[a]]; 42 if(val<c) ans=max(val,ans); 43 } 44 if(bl[a]!=bl[b]) 45 for(int i=(bl[b]-1)*blo+1;i<=b;i++) 46 { 47 int val=v[i]+atag[bl[b]]; 48 if(val<c) ans=max(val,ans); 49 } 50 for(int i=bl[a]+1;i<=bl[b]-1;i++) 51 { 52 int x=c-atag[i]; 53 set<int>::iterator it=st[i].lower_bound(x); 54 if(it==st[i].begin()) continue; 55 --it; 56 ans=max(ans,*it+atag[i]); 57 } 58 return ans; 59 } 60 61 int main() 62 { 63 n=read();blo=1000; 64 for(int i=1;i<=n;i++) v[i]=read(); 65 for(int i=1;i<=n;i++) 66 { 67 bl[i]=(i-1)/blo+1; 68 st[bl[i]].insert(v[i]); 69 } 70 for(int i=1;i<=n;i++) 71 { 72 int f=read(),a=read(),b=read(),c=read(); 73 if(f==0) add(a,b,c); 74 if(f==1) printf("%d\n",query(a,b,c)); 75 } 76 }
注意分块儿大小,瞎改容易RE