教主的魔法

╄→гoц情女王★ 提交于 2019-11-27 16:44:32
问题:
教主最近学会了一种神奇的魔法,能够使人长高。于是他准备演示给XMYZ信息组每个英雄看。于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1、2、……、N
每个人的身高一开始都是不超过1000的正整数。教主的魔法每次可以把闭区间[LR](1≤LRN)内的英雄的身高全部加上一个整数W。(虽然L=R时并不符合区间的书写规范,但我们可以认为是单独增加第LR)个英雄的身高)
CYZ、光哥和ZJQ等人不信教主的邪,于是他们有时候会问WD闭区间 [LR] 内有多少英雄身高大于等于C,以验证教主的魔法是否真的有效。
WD巨懒,于是他把这个回答的任务交给了你。
 
解:
分块板题
动态区间第k小数
复习一下分块
code:
//  
#include<stdio.h>
#include<bits/stdc++.h>  
using namespace std;  
#define maxnn 2000000  
int n,Q;  
int laz[maxnn];  
int a[maxnn];  
int s;  
int k1,k2;  
int B[6000][6000];  
int cnt[6000];  

  inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
void modify(int x,int y,int z)  
{  
     k1=(x-1)/s+1;  
     k2=(y-1)/s+1;  
    if(k1==k2)  
    {  
        for(int i=x;i<=y;i++)  
        {
            a[i]=a[i]+z;
        }
        cnt[k1]=0;
        for(int i=(k1-1)*s+1;i<=k1*s;i++)
        {
            B[k1][cnt[k1]]=a[i];
            cnt[k1]++;
        }
    }  
    else  
    {  
        for(int i=x;i<=k1*s;i++)  
        {
            a[i]=a[i]+z;
        }
        cnt[k1]=0;
        for(int i=(k1-1)*s+1;i<=k1*s;i++)
        {
            B[k1][cnt[k1]]=a[i];
            cnt[k1]++;
        }
        
         for(int i=(k2-1)*s+1;i<=y;i++)  
        {
            a[i]=a[i]+z;
        }
         cnt[k2]=0;
        for(int i=(k2-1)*s+1;i<=k2*s;i++)
        {
            B[k2][cnt[k2]]=a[i];
            cnt[k2]++;
        }
        for(int i=k1+1;i<k2;i++)  
        {  
            laz[i]+=z;   
        }  
    }  
    
        sort(B[k1],B[k1]+cnt[k1]);    
           sort(B[k2],B[k2]+cnt[k2]);  
}  
int query(int x,int y,int z)  
{  
    int k1=(x-1)/s+1;  
    int k2=(y-1)/s+1;  
    int ans=0;  
    if(k1==k2)  
    {  
        for(int i=x;i<=y;i++)  
        {  
            if(a[i]+laz[k1]>=z) ans++;  
        }  
    }  
    else  
    {  
        for(int i=x;i<=k1*s;i++)  
        if(a[i]+laz[k1]>=z) ans++;  
        for(int i=(k2-1)*s+1;i<=y;i++)  
        {  
            if(a[i]+laz[k2]>=z) ans++;  
        }  
            for(int i=k1+1;i<k2;i++)  
        {  
            ans+=(cnt[i]-(lower_bound(B[i],B[i]+cnt[i],z-laz[i])-B[i]));  
        }  
    }  
    return ans;  
}  
int main()  
{  
    char ch;  
    
    n=read();
    Q=read();
    
    int x,y,z;  
    for(int i=1;i<=n;i++)  
    {  
       a[i]=read(); 
    }  
     s=int(sqrt(n));  
    for(int i=1;i<=n;i++)  
    {  
        int k=(i-1)/s+1;  
        B[k][cnt[k]]=a[i]; 
        cnt[k]++;  
    }  
    for(int i=1;i<=s+1;i++)  
    {  
        sort(B[i],B[i]+cnt[i]);  
    }  
    while(Q--)  
    {  
        cin>>ch;  
          
        if(ch=='A')  
        {  
            x=read();y=read();
            z=read();  
            cout<<query(x,y,z)<<endl;  
        }  
        else  
        {  
            
            x=read();y=read();
            z=read();   
            modify(x,y,z);  
        }  
    }  
}

 

 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!