训练日志9.13

今天学了一下分块,维护中间的块,然后两边的零散的暴力一下.

P2801 教主的魔法

分块的板子题,主要简单维护一下中间的块

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;

int n,q;
int block,cnt;
int belong[N],val[N],mark[(N>>2)+10];
vector<int>kuai[(N>>2)+10];
void init(){
    for(int i=1;i<=cnt;i++){
        sort(kuai[i].begin(),kuai[i].end());
    }
}
void update(int u){
    kuai[u].clear();
    for(int i=(u-1)*block+1;i<=u*block;++i)
        kuai[u].push_back(val[i]);
    sort(kuai[u].begin(),kuai[u].end());
}
void add(int l,int r,int x){
    for(int i=l;i<=min(r,belong[l]*block);++i)
        val[i]+=x;
    update(belong[l]);
    if(belong[l]!=belong[r]){
        for(int i=belong[l]+1;i<belong[r];++i)
            mark[i]+=x;
        for(int i=(belong[r]-1)*block+1;i<=r;++i)
            val[i]+=x;
        update(belong[r]);
    }
}
int search(int l,int r,int x){
    int num(0);
    for(int i=l;i<=min(r,belong[l]*block);++i)
        if(val[i]+mark[belong[i]]>=x)++num;
    if(belong[l]!=belong[r]){
        for(int i=belong[l]+1;i<belong[r];++i){
            int l1=0,r1=block-1;
            while(l1<=r1){
                int mid=l1+((r1-l1)>>1);
                if(kuai[i][mid]+mark[i]<x)l1=mid+1;
                else r1=mid-1;
            }
            num+=block-l1;
        }
        for(int i=(belong[r]-1)*block+1;i<=r;++i)
            if(val[i]+mark[belong[i]]>=x)++num;
    }
    return num;
}
signed main(){

    cin>>n>>q;

    block=sqrt(n);
    for(int i=1;i<=n;i++){
        cin>>val[i];
        if(i%block==1)cnt++;
        belong[i]=cnt;
        kuai[cnt].push_back(val[i]);
    }
    init();
    char op;
    while(q--){
        int L,R,u;
        cin>>op>>L>>R>>u;
        if(op=='M'){
            add(L,R,u);
        }
        else{
            cout<<search(L,R,u)<<endl;
        }
    }   
    return 0;
}

acwing249. 蒲公英

还是太菜了,调了几个小时没调出来qwq,感觉代码细节上有问题,等过几天再写一下qwq

这题给的数据范围很大,所以首先要离散化,然后用前缀和优化,超了,然后题解要用了预处理,

代码就不贴了,下次吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值