P5356 [Ynoi2017] 由乃打扑克

news2024/11/25 0:33:55

我手把手教她打扑克 qwq

综合分析一下2个操作,查找区间第k小的值,感觉可以用主席树,区间修改那没事了

考虑分块做法,块长B

分析第一个操作

只需要维护数列的单调性,然后二分答案上二分就ok了

分析第二个操作

维护一个加法懒标记即可

口胡了一下感觉很简单

仔细分析一下第一个操作

二分找到一个“第k小值”,再进行check,check的过程中散块遍历一遍,整块二分找到最后一个小于等于x的(只有前面部分有贡献),分析一下时间复杂度,预处理 O(\frac{n}{B}*BlogB),(分块完排序),二分答案O(\frac{n}{B}*lognlogV),二分O(\frac{n}{B}*BlogB)

第二个操作

散块可以暴力然后重构,整块上懒标记,时间复杂度O(\frac{n}{B}*B*logB)

总时间复杂度O(m*\frac{n}{B}*lognlogV)    maybe..

应该需要优化?

分析一下二分答案这块,我们不一定要把L定义无穷小,R定义无穷大,可以维护一下区间最大值区间最小值这样可以转化为O(\frac{n}{B}*logn)差不多能卡过去了,我是这样干的,二分剪枝一下

分析一下散块区间加,不一定要O(BlogB)的排序,我们可以把数列分成2块,没有加的和加的,两边其实都是有序的,因此可以用归并排序优化成O(B)

快长最优可能是sqrt(n)logn..

小优化

1.不一定要把散块重构,如果没有询问到,可以不做,我们用线段树区间赋值的思想,修改后标记一下这个块需要重构,等询问的时候问到了再进行重构

void work(int l,int r){
    int p=pos[l];
    int q=pos[r];
    for(int i=p;i<=q;i++){
        if(re[i]){
            rebuild(i);
            re[i]=0;
        }
    }
}

2.二分答案优化

    if(k<1 || R-L+1<k){
            return -1;
    }

3.块内二分优化

    if(v[id].front()+add[id]>x){//没有比x小的
        return 0;
    }
    if(v[id].back()+add[id]<=x){//都是小于等于x的
        return r+1;//r-0+1;
    }

4.维护区间最大值最小值优化

    for(int i=p+1;i<=q-1;i++){//最后一个是最大
        res=max(res,v[i].back()+add[i]);
    }
    for(int i=p+1;i<=q-1;i++){//第一个是最小
        res=min(res,v[i].front()+add[i]);
    }

完整代码

#include<iostream>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<cstring>
#include<vector>
#define INF (1ll<<60)
using namespace std;
typedef long long ll;
const int N=1e5+9;
const int B=1e4+9;
namespace Lan {
    inline string sread() {
        string s=" ";char e=getchar();
        while(e==' '||e=='\n')e=getchar();
        while(e!=' '&&e!='\n')s+=e,e=getchar();
        return s;
    }
    inline void swrite(string s){
        for(char e:s)putchar(e);
        printf("\n");
    }
    inline ll read() {
        ll x=0,y=1;char c=getchar();
        while(!isdigit(c)){if(c=='-')y=-1;c=getchar();}
        while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
        return x*=y;
    }
    inline void write(ll x) {
        if(x<0){x=-x,putchar('-');}ll sta[35],top=0;
        do sta[top++]=x%10,x/=10;while(x);
        while(top)putchar(sta[--top]+'0');
    }
}using namespace Lan;
ll a[N];
int L[B],R[B],pos[N];
ll add[B];
int re[B];
vector<ll> v[B];
inline void rebuild(int id){
    v[id].clear();
    for(int i=L[id];i<=R[id];i++){
        v[id].push_back(a[i]);
    }
    sort(v[id].begin(),v[id].end());
}
inline int binary(int id,int x){
    int l=0,r=v[id].size()-1;
    if(v[id].front()+add[id]>x){//没有比x小的
        return 0;
    }
    if(v[id].back()+add[id]<=x){//都是小于等于x的
        return r+1;//r-0+1;
    }
    int res=0;
    while(l<=r){
        int mid=(l+r)>>1;
        if(v[id][mid]+add[id]<=x){//小于等于x,选大一点
            l=mid+1;
            res=mid+1;//小于等于x的有贡献
        }else{
            r=mid-1;
        }
    }
    return res;
}
inline ll getmax(int l,int r){
    ll res=-INF;
    int p=pos[l];
    int q=pos[r];
    if(p==q){
        for(int i=l;i<=r;i++){
            res=max(res,a[i]+add[pos[i]]);
        }
    }else{
        for(int i=l;i<=R[p];i++){
            res=max(res,a[i]+add[pos[i]]);
        }
        for(int i=L[q];i<=r;i++){
            res=max(res,a[i]+add[pos[i]]);
        }
        for(int i=p+1;i<=q-1;i++){//最后一个是最大
            res=max(res,v[i].back()+add[i]);
        }
    }   
    return res;
}
inline ll getmin(int l,int r){
    ll res=INF;
    int p=pos[l];
    int q=pos[r];
    if(p==q){
        for(int i=l;i<=r;i++){
            res=min(res,a[i]+add[pos[i]]);
        }
    }else{
        for(int i=l;i<=R[p];i++){
            res=min(res,a[i]+add[pos[i]]);
        }
        for(int i=L[q];i<=r;i++){
            res=min(res,a[i]+add[pos[i]]);
        }
        for(int i=p+1;i<=q-1;i++){//第一个是最小
            res=min(res,v[i].front()+add[i]);
        }
    }
    return res;
}
inline int check(int l,int r,int x){
    int p=pos[l];
    int q=pos[r];
    int res=0;
    if(p==q){
        for(int i=l;i<=r;i++){
            if(a[i]+add[pos[i]]<=x){
                res++;
            }
        }
    }else{
        for(int i=l;i<=R[p];i++){
            if(a[i]+add[pos[i]]<=x){
                res++;
            }
        }
        for(int i=L[q];i<=r;i++){ 
            if(a[i]+add[pos[i]]<=x){
                res++;
            }
        }
        for(int i=p+1;i<=q-1;i++){
            res+=binary(i,x);
        }
    }
    return res;
}
void work(int l,int r){
    int p=pos[l];
    int q=pos[r];
    for(int i=p;i<=q;i++){
        if(re[i]){
            rebuild(i);
            re[i]=0;
        }
    }
}
inline int kth(int k,int L,int R){
    if(k<1 || R-L+1<k){
        return -1;
    }
    work(L,R);
    int res=-1;
    ll l=getmin(L,R),r=getmax(L,R);
    while(l<=r){
        ll mid=(l+r)>>1;
        if(check(L,R,mid)<k){//选的值太小
            l=mid+1;
        }else{
            r=mid-1;
            res=mid;
        }
    }
    return res;
}
inline void modify(int l,int r,int k){
    int p=pos[l];
    int q=pos[r];
    if(p==q){
        for(int i=l;i<=r;i++){
            a[i]+=k;
        }
        re[p]=1;
        // rebuild(p);
    }else{
        for(int i=l;i<=R[p];i++){
            a[i]+=k;
        }
        re[p]=1;
        // rebuild(p);
        for(int i=p+1;i<=q-1;i++){
            add[i]+=k;
        }
        for(int i=L[q];i<=r;i++){
            a[i]+=k;
        }
        re[q]=1;
        // rebuild(q);
    }
}
int main(){
    // ios::sync_with_stdio(false);
    // cin.tie(0),cout.tie(0);
    int n,m;
    n=read();
    m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    int blo=sqrt(n);
    int t=ceil(1.0*n/blo);
    for(int i=1;i<=t;i++){
        L[i]=(i-1)*blo+1;
        R[i]=(i==t?n:i*blo);
    }
    for(int i=1;i<=t;i++){
        for(int j=L[i];j<=R[i];j++){
            pos[j]=i;
        }
    }
    for(int i=1;i<=n;i++){
        v[pos[i]].push_back(a[i]);
    }
    for(int i=1;i<=t;i++){
        sort(v[i].begin(),v[i].end());
    }
    for(int i=1;i<=m;i++){
        int op,l,r,k;
        op=read();
        l=read();
        r=read();
        k=read();
        if(op==1){
            write(kth(k,l,r));
            putchar('\n');
        }else{
            modify(l,r,k);
        }
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1580671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

比较好玩的车子 高尔夫6

https://www.sohu.com/a/484063087_221273 四万多如愿收获手动挡高尔夫6&#xff0c;可靠性、经济性、操控性兼顾_搜狐汽车_搜狐网 2.基本上其他人也不知道到底是什么相关的车子信息

HarmonyOS 开发-自定义视图实现Tab效果

介绍 本示例介绍使用Text、List等组件&#xff0c;添加点击事件onclick,动画&#xff0c;animationTo实现自定义Tab效果。 效果预览图 使用说明 点击页签进行切换&#xff0c;选中态页签字体放大加粗&#xff0c;颜色由灰变黑&#xff0c;起到强调作用&#xff0c;同时&…

鸿蒙HarmonyOS开发实例:【简单时钟】

简单时钟 介绍 本示例通过使用[ohos.display]接口以及Canvas组件来实现一个简单的时钟应用。 效果预览 主页 使用说明 1.界面通过setInterval实现周期性实时刷新时间&#xff0c;使用Canvas绘制时钟&#xff0c;指针旋转角度通过计算得出。 例如&#xff1a;"2 * M…

第十课 Excel

最上方标题栏&#xff1a; 显示共工作薄名称&#xff0c;如果显示兼容模式是没有办法使用高级功能的。分辨高版本和低版本可以通过后缀名进行分辨&#xff1b;显示xlsx就是高版本工作薄&#xff0c;如果显示xls的话就是低版本工作薄了。如果同事老板都使用的是低版本的话我们发…

【攻防世界】Web_python_template_injection

{{}}是变量包裹标识符&#xff0c;里面存放的是一个变量&#xff0c;当你输入 http://61.147.171.105:55121/{{8*8}} 执行成功&#xff0c;说明存在模版注入。接下来&#xff0c;开始想办法编代码拿到服务器的控制台权限 。 首先&#xff0c;题目告诉我们这是一个 python 注入…

机器学习(五) -- 监督学习(2) -- k近邻

系列文章目录及链接 目录 前言 一、K近邻通俗理解及定义 二、原理理解及公式 1、距离度量 四、接口实现 1、鸢尾花数据集介绍 2、API 3、流程 3.1、获取数据 3.2、数据预处理 3.3、特征工程 3.4、knn模型训练 3.5、模型评估 3.6、结果预测 4、超参数搜索-网格搜…

【环境搭建】ubuntu工作站搭建全流程(显卡4090)

安装ubuntu22.04系统 首先&#xff0c;先压缩windows分区&#xff0c;按住Win X快捷键&#xff0c;选择磁盘管理,压缩分区&#xff0c;压缩出新的分区用于安装ubuntu22.04 windows插入系统盘&#xff0c;点击重启&#xff0c;一直按F12,选择系统盘启动方式语言选择chinese–…

AI技术将影响更长远,比如未来的就业形势

随着人工智能渗透到工作场所&#xff0c;人类将需要掌握新的工作技能。 AI作为新技术已经开始扰乱就业市场了。对于最新的AI人工智能技术&#xff0c;经济学家、教育工作者、监管机构、商业分析师以及相关领域专家预测&#xff0c;在不久的将来&#xff0c;人工智能一代将需要…

Python常用算法思想--回溯算法思想详解【附源码】

通过回溯算法解决“组合”问题、“排序”问题、“搜索”之八皇后问题、“子集和”之0-1背包问题、字符串匹配等六个经典案例进行介绍: 一、解决“组合”问题 从给定的一组元素中找到所有可能的组合,这段代码中的 backtrack_combinations 函数使用了回溯思想,调用 backtrack…

25.11 MySQL 视图

1. 常见的数据库对象 对象描述表(TABLE)存储数据的逻辑单元, 以行和列的形式存在, 列就是字段, 行就是记录.数据字典系统表, 存放数据库相关信息的表. 数据通常由数据库系统维护, 程序员通常不可修改, 只可查看.约束(CONSTRAINT)执行数据校验的规则, 用于保证数据完整性的规则…

抓住风口,快速上手RAG应用开发!

免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案」&#xff1b; 不要急着评判文章列出的观点&#xff0c;只需代入其中&#xff0c;适度…

OpenHarmony开发-连接开发板调试应用

在 OpenHarmony 开发过程中&#xff0c;连接开发板进行应用调试是一个关键步骤&#xff0c;只有在真实的硬件环境下&#xff0c;我们才能测试出应用更多的潜在问题&#xff0c;以便后续我们进行优化。本文详细介绍了连接开发板调试 OpenHarmony 应用的操作步骤。 首先&#xf…

RK3568---4G模块驱动实验

作者简介&#xff1a; 一个平凡而乐于分享的小比特&#xff0c;中南民族大学通信工程专业研究生在读&#xff0c;研究方向无线联邦学习 擅长领域&#xff1a;驱动开发&#xff0c;嵌入式软件开发&#xff0c;BSP开发 作者主页&#xff1a;一个平凡而乐于分享的小比特的个人主页…

【攻防世界】wife_wife

原型链污染 源码 app.post(/register, (req, res) > {let user JSON.parse(req.body)if (!user.username || !user.password) {return res.json({ msg: empty username or password, err: true })}if (users.filter(u > u.username user.username).length) {return …

iOS App Store审核要求与Flutter应用的兼容性分析

本文探讨了使用Flutter开发的iOS应用能否上架&#xff0c;以及上架的具体流程。苹果提供了App Store作为正式上架渠道&#xff0c;同时也有TestFlight供开发者进行内测。合规并通过审核后&#xff0c;Flutter应用可以顺利上架。但上架过程可能存在一些挑战&#xff0c;因此可能…

网格矢量如何计算莫兰指数

网格矢量如何计算莫兰指数 引言 遇到一个问题&#xff0c;计算矢量网格的莫兰指数。 概念解释 莫兰指数 莫兰指数&#xff08;Moran’s Index&#xff09;是一种空间自相关指标&#xff0c;用于衡量空间数据的相似性和聚集程度。它可以用来描述一个区域与其邻近区域之间的属…

web攻防——js

1.php和js的区别 他只有这一行&#xff08;所以它是解析形语言&#xff09;而js写了什么&#xff0c;看源代码就显示什么 安装

性能分析-数据库与磁盘知识

数据库 数据库&#xff0c;其实是数据库管理系统dbms。 数据库管理系统&#xff0c; 常见&#xff1a; 关系型数据库&#xff1a; mysql、pg、 库的表&#xff0c;表与表之间有关联关系&#xff1b; 表二维表统一标准的SQL&#xff08;不局限于CRUD&#xff09;非关系型数据…

代码随想录day35 | 贪心算法P4 | ● 860 ● 406 ● 452

860.柠檬水找零 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确…

共享云桌面和虚拟云桌面优劣势对比分析

随着云计算技术的不断发展&#xff0c;共享云桌面和虚拟云桌面成为了企业信息化建设的热门选择。共享云桌面和虚拟云桌面这两种技术各有优劣势&#xff0c;下面我们将对它们进行对比分析。 首先&#xff0c;我们来了解一下共享云桌面的优势。共享云桌面是指多个用户通过云平台…