【学习笔记】CF1375
创始人
2024-06-02 22:27:50
0

这题需要自己构造过程。但是我这方面能力比较差所以还是不会做

显然倒着考虑。如果先手胜利的话那么a,b,ca,b,ca,b,c一定构成等差数列,并且上一次操作的是ccc。

再往前倒推一步。接下来就非常有运气成分了:假设ccc不能操作,并且任意操作a,ba,ba,b都会构成等差数列,解方程算出来k=2c−a−bk=2c-a-bk=2c−a−b恰好有解,这道题就做完了。

注意到是对相邻的点进行操作,因此猜测存在距离之类的不变量。

假设固定了根节点,那么问题转化为将所有点到根的距离变成111,不难发现操作过程中只有一个点距离的奇偶性发生变化,猜测这就是答案的下界。取等分析就不说了。

向来不会工业题

首先考虑一个操作次数N2N^2N2的解法,我们需要求出所有区间对应的集合

令M=⌊N2⌋M=\lfloor\frac{N}{2}\rfloorM=⌊2N​⌋,首先求出数组aia_iai​权值在[1,M][1,M][1,M]的子序列对应的所有集合,以及数组aia_iai​权值在[M+1,N][M+1,N][M+1,N]的子序列对应的所有集合,那么原数组的任意区间都可以由至多一次操作拼出。不难验证操作次数不会超过N2N^2N2。

因为这题很考验代码实现能力,所以还是梳理一下代码实现的细节,不然写起来非常想死

对于原问题,我们考虑对权值进行分块处理 一开始想的是按序列进行分块但是就是很难写所以写不出来,应该是想复杂了 ,对于每一个值域块,我们提取出[l:r][l:r][l:r](询问区间)中在值域块内的数的子序列加入答案,那么对于一个值域块,我们要维护[l,r][l,r][l,r]所对应的答案,转化到子序列中就是[l′,r′][l',r'][l′,r′]对应的答案。于是只用考虑怎么合并。首先求出[l,M],[M+1,r][l,M],[M+1,r][l,M],[M+1,r]对应的答案(这可以用一个结构体来维护),然后枚举区间,把它在左右两段值域中所对应的两个区间合并起来就是答案。这个地方可以直接二分查找 因为这样比较好写 。取B=QB=\sqrt{Q}B=Q​,操作次数我们之前分析过了是2NQ2N\sqrt{Q}2NQ​次,恰好可以通过。

权衡利弊后,发现还是写一下吧,要是代码能力再退步那就寄了

为了避免繁琐的空间问题,我选择使用vector\text{vector}vector。

这题也引发了我的思考。遇到这样代码比较复杂的题目,能不能在考场上迅速想到最好实现的那种方法呢?因为我们知道数据结构题实现思路不清晰的话甚至不如暴力。那么我们要冷静下来分析,必要时可以牺牲少量常数换取代码长度,这是对我这样代码能力“不那么强”的oier所需要的。

#include
#define pb push_back
#define fi first
#define se second
#define inf 0x3f3f3f3f
using namespace std;
const int N=(1<<12)+5;
const int M=(1<<16)+5;
const int B=1<<8;
int n,m,Q,a[N],b[N],id[M];
vector>ans;
struct node{vector>v;vectorp;//原序列中的位置 void init(int l,int r){int len=r-l+1;v.resize(len);for(int i=0;iint ql=lower_bound(p.begin(),p.end(),l)-p.begin(),qr=upper_bound(p.begin(),p.end(),r)-p.begin()-1;if(ql<=qr)return v[ql][qr];return 0;}
}res[N];
int merge(int x,int y){if(!x||!y)return x+y;ans.pb({x,y});return ++m;
}
node getres(int l,int r){node ans;ans.init(l,r);if(l==r){ans.v[0][0]=b[l];return ans;}int mid=l+r>>1;node L=getres(l,mid),R=getres(mid+1,r);int n=r-l+1;for(int i=0;ifor(int j=i;jans.v[i][j]=merge(L.ask(ans.p[i],ans.p[j]),R.ask(ans.p[i],ans.p[j]));}}return ans;
}
int main(){ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);cin>>n>>Q;m=n;for(int i=1;i<=n;i++)cin>>a[i],b[a[i]]=i;for(int i=1;i<=(n-1)/B+1;i++){int l=(i-1)*B+1,r=min(n,i*B);res[i]=getres(l,r);}for(int i=1;i<=Q;i++){int l,r,cur=0;cin>>l>>r;for(int j=1;j<=(n-1)/B+1;j++){cur=merge(cur,res[j].ask(l,r));}id[i]=cur;}cout<

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...