新年快乐
新年快乐
维护⼀个序列 $a$ , 长度为 $n$ , 要求⽀持:
$1.~1~ l~ r~ v$, 对区间 $[l, r]$ 中的每个数字都加上 $v$ 。
$2.~2~ l~ r~ k$, 统计有多少个在区间 $[l, r]$ 中的数字满⾜他的值不超过$k$ 。
Sol
考虑分块,对于块内用个vector维护。
单点改就暴力重建,整块就打标记。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<vector> 8 #define maxn 200005 9 #define ll long long 10 using namespace std; 11 int n,o,ans; 12 ll a[maxn]; 13 struct node{ 14 int l,r,ne; 15 ll bj; 16 vector<ll>v; 17 }s[1005]; 18 void ask(int id,ll v){ 19 if(s[id].ne){ 20 for(int i=s[id].l;i<=s[id].r;i++)a[i]+=s[id].bj; 21 s[id].v.clear(); 22 for(int i=s[id].l;i<=s[id].r;i++)s[id].v.push_back(a[i]); 23 sort(s[id].v.begin(),s[id].v.end()); 24 s[id].ne=0;s[id].bj=0; 25 } 26 int l=0,r=s[id].v.size()-1; 27 while(l<r){ 28 int mid=l+r+1>>1; 29 if(s[id].v[mid]+s[id].bj<=v)l=mid; 30 else r=mid-1; 31 } 32 ans+=(s[id].v[l]+s[id].bj<=v)?l+1:l; 33 } 34 int main() 35 { 36 cin>>n; 37 for(int i=1;i<=n;i++)scanf("%lld",&a[i]); 38 int o=sqrt(n); 39 for(int i=0;i<=n;i++){ 40 s[i].l=i*o;s[i].r=s[i].l+o-1; 41 s[i].l=max(s[i].l,1);s[i].r=min(s[i].r,n); 42 if(s[i].r==n)break; 43 s[i].ne=1; 44 } 45 int m;cin>>m; 46 for(int i=1,op,l,r;i<=m;i++){ 47 scanf("%d",&op);ll v; 48 scanf("%d%d%lld",&l,&r,&v); 49 if(op==1){ 50 int li=l/o,ri=r/o; 51 for(int j=li+1;j<ri;j++)s[j].bj+=v; 52 for(;l<s[li+1].l&&l<=r;l++)a[l]+=v; 53 for(;r>s[ri-1].r&&r>=l;r--)a[r]+=v; 54 s[li].ne=s[ri].ne=1; 55 } 56 else { 57 int li=l/o,ri=r/o;ans=0; 58 for(int j=li+1;j<ri;j++)ask(j,v); 59 for(;l<s[li+1].l&&l<=r;l++)if(a[l]+s[li].bj<=v)ans++; 60 for(;r>s[ri-1].r&&r>=l;r--)if(a[r]+s[ri].bj<=v)ans++; 61 printf("%d\n",ans); 62 } 63 } 64 return 0; 65 }