首页 > 其他分享 >[68] (炼石计划) NOIP 模拟赛 #20

[68] (炼石计划) NOIP 模拟赛 #20

时间:2024-11-14 19:07:41浏览次数:1  
标签:20 炼石 NOIP int mid pos add del ans

学了一个挺帅的 MerMaid

所以用一下

MerMaid 就是你们接下来会看到的好看小标题

但是实际上它是用来画流程图的……

flowchart TB A(邻间的骰子之舞) style A color:#ffffff,fill:#00c0c0,stroke:#ffffff

考虑每次复制以后一定会粘贴若干次(大于零,否则没有意义),因此将复制粘贴捆绑起来考虑,设复制后连续粘贴了 \(m\) 次,则代价为 \(x+my\),贡献为让编辑器内文字个数变为 \(m+1\) 倍

假设我们做了 \(k\) 次上述操作,第 \(i\) 次操作的粘贴次数为 \(m_i\),则

  • 总贡献为 \(\prod\limits^k_i(m_i+1)\)
  • 总代价为 \(\sum\limits^k_i(x+m_iy)\)

根据题意,我们需要 \(\prod\limits^k_i(m_i+1)\gt n\),在此基础上总代价最小

转化一下总代价的式子

\[\begin{aligned}ans&=\sum^k_i(x+m_iy)\\&=kx+y\sum^k_im_i\end{aligned} \]

当 \(k\) 不变时,\(kx\) 项不变,等价于求 \(\sum^k_im_i\) 的最小值

引理:最优答案中不存在 \(i,j\),使得 \(m_i-m_j\gt 1\)

证明:设 \(m_i-m_j\gt 1\),因为 \((m_i-1)(m_j+1)=m_im_j+m_i-m_j-1=m_i(m_j+1)\gt m_im_j\),故其一定不是最优解

因此设最终答案中最小的数为 \(t\),则最大的可能值一定为 \(t+1\),如果我们钦定有 \(p\) 个 \(t\),则题目中条件等价于 \(t^p\times (t+1)^{k-p}\gt n\),可以枚举所有可能的 \(p\),通过二分答案找到最小的 \(t\) 的可能值来计算贡献

在外层枚举 \(k\) 即可,\(k\le log_2n\),因此复杂度为枚举 \(k\) 套枚举 \(p\) 套二分答案套快速幂,\(\log^4n\)

记得开 int128



#include<bits/stdc++.h>
#define int __int128
using namespace std;
long long n,x,y;
int power(int a,int t){
	int base=a,ans=1;
	while(t){
		if(t&1){
            ans=ans*base;
        }
		base=base*base;
		t>>=1;
	}
	return ans;
}
signed main(){
	int res=0x7fffffffffffffff;
	cin>>n>>x>>y;
	for(int k=1;k<=n and clock()<=0.85*CLOCKS_PER_SEC;++k){
		for(int i=0;i<=k;++i){
			int l=2,r=ceil(pow(n,(double)1/k)*2),ans=-1;
			while(l<=r){
				int mid=(l+r)/2;
				if(power(mid,i)*power(mid+1,k-i)>n){
                    ans=mid;
                    r=mid-1;
                }
				else l=mid+1;
			}
			if(ans==-1) continue;
			res=min(res,(__int128)k*x+((__int128)(ans-1)*i+(__int128)ans*(k-i))*(__int128)y);
		}
	}
	cout<<(long long)res;
}
flowchart TB A(星海浮沉录) style A color:#ffffff,fill:#00c0c0,stroke:#ffffff

暴力思路:可以处理出值域上每个值在原数列上的最大不出现长度 \(l_i\)(形式化地,\(l_i\) 为满足存在 \(j\),使得 \(\forall k\in[j,j+l_i-1],a_k\neq i\) 的最大值),然后对这个最大长度做前缀 \(\max\),这样就可以二分答案了,修改 \(n\) 查询 \(\log n\)

优化思路:对值域建线段树,每个点 \(i\) 记录 \(l_i\),这样查询前缀 \(\max\) 相当于查区间最值,不用重构 \(\max\) 数组,然而并没有什么优化,修改 \(n\) 查询 \(\log^2n\)

再次优化思路:由于单点修改只影响相邻的两个区间的长度,因此考虑只改变这两个区间的值

可以想到对每个值维护一个 set,记录每个值的位置,方便查询其前驱,后继,然后算出距离后进行删除,那么我们就还需要一种数据结构来支持快速删除,插入,查询最大值

赛时卡这了,没想到解法竟然是无脑上两颗优先队列

对值域上每个值开两个优先队列,一个表示现有的值,一个表示删除的值

  • 加入操作:直接放进现有值的优先队列
  • 删除操作:直接放进删除的值的优先队列
  • 查询最大值操作:由于删除队列内的值一定是加入操作内的值的子集,因此如果当前现有值队列的对首已经被删除,则它也一定是删除值队列的对首,因此只需要判断两个队列的对首是否相等即可

修改 \(\log n\) 查询 \(\log^2n\)



#include<bits/stdc++.h>
using namespace std;
int n,q;
int a[500001];
int lstpos[500001];
namespace stree{
    struct tree{
        int maxn;
    }t[500001*4];
    #define tol (id*2)
    #define tor (id*2+1)
    #define mid(l,r) mid=((l)+(r))/2
    void change(int id,int l,int r,int pos,int val){
        if(l==r){
            t[id].maxn=val;
            return;
        }
        int mid(l,r);
        if(pos<=mid) change(tol,l,mid,pos,val);
        else change(tor,mid+1,r,pos,val);
        t[id].maxn=max(t[tol].maxn,t[tor].maxn);
    }
    int ask(int id,int l,int r,int L,int R){
        if(L<=l and r<=R){
            return t[id].maxn;
        }
        int mid(l,r);
        if(R<=mid) return ask(tol,l,mid,L,R);
        else if(L>=mid+1) return ask(tor,mid+1,r,L,R);
        return max(ask(tol,l,mid,L,mid),ask(tor,mid+1,r,mid+1,R));
    }
}
set<int>pos[500001];
struct getmax_t{
    priority_queue<int> add_t,del_t;
    inline void add(int x){
        add_t.push(x);
    }
    inline void del(int x){
        del_t.push(x);
    }
    inline int max(){
        while(del_t.empty()==false and del_t.top()==add_t.top()){
            del_t.pop();
            add_t.pop();
        }
        return add_t.top();
    }
};
getmax_t maxn[500001];
inline void add(int _pos){
    pos[a[_pos]].insert(_pos);
    auto iter1=pos[a[_pos]].lower_bound(_pos);iter1--;
    auto iter2=pos[a[_pos]].upper_bound(_pos);
    maxn[a[_pos]].add(_pos-*iter1-1);
    maxn[a[_pos]].add(*iter2-_pos-1);
    stree::change(1,1,n+1,a[_pos]+1,maxn[a[_pos]].max());
}
inline void del(int _pos){
    auto iter1=pos[a[_pos]].lower_bound(_pos);iter1--;
    auto iter2=pos[a[_pos]].upper_bound(_pos);
    maxn[a[_pos]].del(_pos-*iter1-1);
    maxn[a[_pos]].del(*iter2-_pos-1);
    pos[a[_pos]].erase(_pos);
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>q;
    for(int i=1;i<=n;++i){
        cin>>a[i];
        maxn[a[i]].add(i-lstpos[a[i]]-1);
        pos[a[i]].insert(i);
        lstpos[a[i]]=i;
    }
    for(int i=0;i<=n;++i){
        pos[i].insert(0);
        pos[i].insert(n+1);
        maxn[i].add(n-lstpos[i]);
        stree::change(1,1,n+1,i+1,maxn[i].max());
    }
    while(q--){
        int opt,x;
        cin>>opt>>x;
        if(opt==1){
            del(x);del(x+1);
            swap(a[x],a[x+1]);
            add(x);add(x+1);
        }
        else{
            int l=0,r=n,ans=n+1;
            while(l<=r){
                int mid=(l+r)/2;
                if(stree::ask(1,1,n+1,1,mid+1)>=x){
                    ans=mid;
                    r=mid-1;
                }
                else l=mid+1;
            }
            cout<<ans<<'\n';
        }
    }
}
flowchart TB A(第八交响曲「千日同升」) style A color:#ffffff,fill:#00c0c0,stroke:#ffffff

这道题用一种比较好玩的方式考了并行排序

部分分解法是常数较大的奇偶排序(多线程冒泡(?))



#include<bits/stdc++.h>
using namespace std;
int n;
int main(){
    cin>>n;
    cout<<((n+1)/2)*2<<endl;
    for(int i=1;i<=((n+1)/2);i++){
        for(int j=1;j+1<=n;j+=2){
            cout<<"CMPSWP R"<<j<<" R"<<j+1<<' ';
        }
        cout<<'\n';
        for(int j=2;j+1<=n;j+=2){
            cout<<"CMPSWP R"<<j<<" R"<<j+1<<' ';
        }
        cout<<'\n';
    }
}

正解用的是比较优秀的双调排序

关于双调排序的学习推荐 这篇文章


这是什么

标签:20,炼石,NOIP,int,mid,pos,add,del,ans
From: https://www.cnblogs.com/HaneDaCafe/p/18546537

相关文章

  • 代码随想录算法训练营第二天| 209.长度最小的子数组、59. 螺旋矩阵 II
    文档讲解:代码随想录视频讲解:代码随想录状态:完成2道题滑动窗口滑动窗口:两个指针一前一后组成滑动窗口,并计算滑动窗口中的元素的问题适用场景:字符串匹配问题、子数组问题、定长问题滑动窗口模板:如果一个字符进入窗口,应该增加windows计数器;如果一个字符将移除窗口的......
  • MX 2025--炼石计划 NOIP 模拟赛 #20
    打得抽象。T3,T4放俩难的板子。由于是MX的题,就不放题意了。邻间的骰子之舞发现复制操作不会超过\(64\)次,而粘贴操作肯定是越均匀越好,直接二分暴力跑就行了。点此查看代码#include<bits/stdc++.h>usingnamespacestd;#definerep(i,s,t,p)for(inti=s;i<=t;i+=p)#......
  • 2024年秋国开电大《建筑结构试验》形考任务1-4
    形考作业一1.下列选项中,()项不属于科学研究性试验。答案:检验结构的质量,说明工程的可靠性2.下列各项,()项不属于工程鉴定性试验。答案:验证结构计算理论的假定3.按试验目的进行分类,可将结构试验分成()。答案:工程鉴定性试验和科学研究性试验4.按试验对象进行分类,可将结构试验分成()......
  • 2024/11/14
    修改数组(蓝桥杯)分数20作者liudan单位石家庄铁道大学给定一个长度为N的数组A=[A1,A2,⋅⋅⋅AN],数组中有可能有重复出现的整数。现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A2,A3,⋅⋅⋅,AN。当修改Ai时,小明会检查Ai是否在A1∼Ai−1中出......
  • 2024.11.14随笔&联考总结
    前言今天联考直接炸纲了。但是不得不说:HEZ的题要比BSZX好多了。联考今天联考题说实话难度应该比较适合我。第一题是推结论的题,我赛时20min想出正解,但是有两个细节没有考虑清楚,导致后来调题调了一个多小时,然后经典开警告但是不看秒了,期望得分100pts,实际0pts。原因bool......
  • PH热榜 | 2024-11-14
    DevNow是一个精简的开源技术博客项目模版,支持Vercel一键部署,支持评论、搜索等功能,欢迎大家体验。[在线预览](https://www.laughingzhu.c1.Vocera标语:利用模拟和监控加速语音代理上线这句话的意思是:通过使用模拟和监控工具,可以更快地开发并上线语音代理。解释:语......
  • CCF - 网易雷火基金项目成果:基于大小模型协同的低资源标注技术|CNCC 2024 演讲实录
    在科技蓬勃发展的时代浪潮中,人工智能领域的每一次突破都离不开持续的科研投入和对前沿技术的不懈探索。2023年,网易伏羲与中国计算机学会(CCF)共同发起了“CCF-网易雷火联合基金”,致力于发挥和利用多方资源优势,加强与海内外青年学者的科研合作,促进中国人工智能等领域尖端技术产业......
  • 【考试题解】NOIP2024(欢乐)加赛3
    目录A.SakurakoandWater题目内容思路代码B.BinomialCoefficients,KindOf题目内容思路代码C.QED'sFavoritePermutation题目内容思路代码D.CardGame题目内容思路代码E.LongWaytobeNon-decreasing题目内容思路代码F.ManyGames题目内容思路代码A.SakurakoandW......
  • MX 炼石计划 NOIP 模拟赛20(我真做过1~19吗?)
    MX炼石计划NOIP模拟赛#20T1邻间的骰子之舞二分答案,发现性质,签到,过。记得开__int128没开,挂30.码:CODE#include<bits/stdc++.h>typedeflonglongll;usingnamespacestd;constintN=2e5+100;#ifdeflinux#definegetchargetchar_unlocked#define......
  • 2024.11.14 NOIP训练赛
    2024.11.14NOIP训练赛Problem对满足以下条件的01矩阵\(A\)计数:行数为\(n+1\)(从\(0\)至\(n\)标号),列数为\(k\)(从\(1\)至\(k\)标号);不存在使得\(A_{0,i}\simA_{n-1,i}\)这\(n\)个数都为\(1\)的列\(i\);存在使得\(A_{1,i}\simA_{n,i}\)这\(n\)......