[CSP-S模拟测试]:旋转子段(数学)
题目描述
$ZYL$有$N$张牌编号分别为$1,2,...,N$。他把这$N$张牌打乱排成一排,然后他要做一次旋转使得旋转后固定点尽可能多。如果第$i$个位置的牌的编号为$i$,我们就称之为固定点。旋转可以被认为是将其中的一个子段旋转$180$度,这意味着子段的第一张牌和最后一张牌交换位置,以及第二张牌和倒数第二张牌交换位置,等等。写一个程序,找到旋转子段(子段长度可以为$1$)。
输入格式
第一行包含一个整数$N$。
第二行有$N$个数,第$i$个数表示旋转之前第$i$个位置的牌的编号。
输出格式
找到固定点最多的旋转所选的子段,输出旋转之后固定点的个数。
样例
样例输入1:
4
3 2 1 4
样例输出1:
4
样例输入2:
2
1 2
样例输出2:
2
数据范围与提示
样例解释:
在样例$1$中,只需要旋转的子段$[3,2,1]$,将排列变成$1\ 2\ 3\ 4$,旋转后所有的牌都为固定点。答案为$4$。
在样例$2$中,所有的牌已经在固定点,旋转子段$[1]$或者子段$[2]$,答案为$2$。
数据范围:
$30\%$的数据满足:$N\leqslant 500$;
$60\%$的数据满足:$N\leqslant 5,000$;
$100\%$的数据满足:$1\leqslant N\leqslant 500,000$。
题解
$30\%$算法:
裸的暴力,直接搞就行了。
可以用$reverse$卡常,但是没什么用。
注意可以不旋转。
时间复杂度:$\Theta(n^3)$。
期望得分:$30$分。
实际得分:$35$分。
$60\%$算法:
枚举旋转中心和旋转半径,思想类似莫队。
时间复杂度:$\Theta(n^2)$。
期望得分:$60$分。
实际得分:$60$分。
$100\%$算法:
先来利用反证法来证明一个问题:如果最优翻转区间是$[l,r]$,那么如果$a[l]\neq r\&\&a[r]\neq l$,则翻转这个区间$a[l]$和$a[r]$一定都不能成为不动点,对答案一定不能做出贡献,选择区间$[l+1,r-1]$一定不劣。
所以,我们要找的区间一定满足$a[l]=r||a[r]=l$,也就是说,翻转之后一定有一个点成为不动点。
根据上面的出的结论,我们还可以知道,答案一定在所有的$[\min(a[i],i),\max(a[i],i)]$中产生。
显然仅仅是这样我们还是会超时,那么考虑如何进行优化。
依次枚举$n$必不可少,我们考虑从查询中入手。
我们还可以知道,一个点在翻转之后成为不动点,在翻转之前一定满足$a[i]+i=a[j]+j$(式中$i,j$分别表示旋转之前的位置和旋转之后的位置)。
可以使用$vector$优化空间复杂度。
时间复杂度:$\Theta(n\log n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
$30\%$算法:
#include<bits/stdc++.h>
using namespace std;
int a[500001];
int ans;
int main()
{
int n;
scanf("%d",&n);
for(register int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==i)ans++;
}
for(register int i=1;i<n;i++)
for(register int j=i+1;j<=n;j++)
{
register int sum=0;
reverse(a+i,a+j+1);
for(register int k=1;k<=n;k++)
if(a[k]==k)sum++;
reverse(a+i,a+j+1);
ans=max(ans,sum);
}
printf("%d",ans);
return 0;
}
$60\%$算法:
#include<bits/stdc++.h>
using namespace std;
int n,ans,now,res,a[500001];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==i)res++;
}
ans=res;
for(int i=1;i<=n;i++)
{
now=res;
for(int j=1;j<=n;j++)
{
int l=i-j,r=i+j;
if(l<=0||r>=n)break;
if(a[l]==r)now++;
if(a[r]==l)now++;
if(a[l]==l)now--;
if(a[r]==r)now--;
ans=max(ans,now);
}
now=res;
for(int j=1;j<=n;j++)
{
int l=i-j+1,r=i+j;
if(l<=0||r>=n)break;
if(a[l]==r)now++;
if(a[r]==l)now++;
if(a[l]==l)now--;
if(a[r]==r)now--;
ans=max(ans,now);
}
}
printf("%d\n",ans);
return 0;
}
$100\%$算法:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[2000000],sum1[2000000],sum2[2000000];
int flag,ans;
vector<int> g[2000000];
bool cmp(int x,int y){return abs((x<<1)-flag)<abs((y<<1)-flag);}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
g[a[i]+i].push_back(i);
if(a[i]==i)sum1[i]=sum2[i]=1;
sum1[i]+=sum1[i-1];
}
for(int i=n;i;i--)sum2[i]+=sum2[i+1];
for(int i=2;i<=(n<<1);i++)
if(!g[i].empty())
{
flag=i;
sort(g[i].begin(),g[i].end(),cmp);
for(int j=0;j<g[i].size();j++)
{
int l=g[i][j];
int r=i-g[i][j];
if(l>r)swap(l,r);
ans=max(ans,sum1[l-1]+sum2[r+1]+j+1);
}
}
cout<<ans<<endl;
return 0;
}
rp++
[CSP-S模拟测试]:旋转子段(数学)的更多相关文章
- [CSP-S模拟测试]:不等式(数学)
题目描述 小$z$热衷于数学.今天数学课的内容是解不等式:$L\leqslant S\times x\leqslant R$.小$z$心想这也太简单了,不禁陷入了深深的思考:假如已知$L,R,S,M$ ...
- [CSP-S模拟测试]:A(数学)
题目传送门(内部题44) 输入格式 一行四个整数,分别表示$S,T,a,b$. 输出格式 输出最小步数,数据保证有解. 样例 样例输入: 10 28 4 2 样例输出: 数据范围与提示 样例解释: 先 ...
- [CSP-S模拟测试]:装饰(数学)
题目传送门(内部题147) 输入格式 每个测试点第一行一个正整数$T$,表示该测试点内的数据组数. 接下来$T$行,每行三个非负整数$a,b,c$,含义如题目中所示. 输出格式 对每组数据输出一行一个 ...
- [CSP-S模拟测试]:最大值(数学+线段树)
题目背景 $Maxtir$最喜欢最大值. 题目传送门(内部题128) 输入格式 第$1$行输入四个正整数$n,m,q$. 第$2$至$n+1$行中,第$i+1$行输入魔法晶石$i$的三种属性$(x_i ...
- [CSP-S模拟测试]:求和(数学)
题目传送门(内部题107) 输入格式 一行五个正整数$x_1,y_1,x_2,y_2,m$ 输出格式 输出一个整数,为所求的答案对$m$取模后的结果. 样例 样例输入: 2 1 5 3 10007 样 ...
- [CSP-S模拟测试]:数列(数学)
题目传送门(内部题95) 输入格式 第一行三个整数$n,a,b$,第二行$n$个整数$x_1\sim x_n$表示数列. 输出格式 一行一个整数表示答案.无解输出$-1$. 样例 样例输入:2 2 3 ...
- [CSP-S模拟测试]:Walker(数学)
题目传送门(内部题86) 输入格式 第一行$n$接下来$n$行,每行四个浮点数,分别表示变换前的坐标和变换后的坐标 输出格式 第一行浮点数$\theta$以弧度制表示第二行浮点数$scale$第三行两 ...
- [CSP-S模拟测试]:Six(数学)
题目传送门(内部题85) 输入格式 一个正整数$N$. 输出格式 一个数表示答案对$1000000007$取模后的结果 样例 样例输入1: 样例输出1: 样例输入2: 样例输出2: 样例输入3: 样例 ...
- [CSP-S模拟测试]:Smooth(数学)
题目传送门(内部题84) 输入格式 两个整数$B,K$ 输出格式 一个整数表示答案 样例 样例输入: 5 100 样例输出: 数据范围与提示 对于$40\%$的数据,保证答案小于$10^7$对于另$2 ...
随机推荐
- python 字典zip使用
- oracle 11g 数据库恢复技术 ---04 rman
四 RMAN RMAN体系结构的主要组成部分: --1 目标数据库(target) --2 RMAN命令行客户端 --3 通道(channel) --4 快速恢复区(fast recovery are ...
- OO第四单元单元总结
目录 1.本单元两次作业的架构设计 2.四个单元中架构设计及OO方法理解的演进 3.测试理解与实践的演进 4.课程收获 5.给课程的改进建议 1.本单元两次作业的架构设计 第四单元的两次作业,我的表现 ...
- 强化学习-K摇臂赌博机
在强化学习任务中,学习的目的就是找到能够长期累积奖赏最大化的策略.这里的策略实际上就相当于监督学习中的分类器或回归器,模型的形式并无差别.但不同的是,在强化学习中并没有监督学习中的有标记样本,换言之, ...
- 解决django项目在ubuntu系统上无法安装mysqlclient
首先我的项目是django2.0,python环境是3.5. 我们在本地开发完django项目了,在本地运行是成功的,然后我们把django项目放到服务器上,运行的时候就出错了. 如图: 我们都知道, ...
- ceph部署-集群建立
一.配置storage集群1.建立集群管理目录(管理配置文件,密钥)mkdir ceph-clustercd ceph-cluster/ 2.创建一个新集群(需要先将主机名加入/etc/hosts 必 ...
- 剑指Offer编程题(Java实现)——数组中的重复数字
题目描述 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的.也不知道每个数字重复几次.请找出数组中任意一个重复的数字. 例如,如果输入长度为 ...
- python 导入re模块语法及规则
正则表达式是功能比较强大的模块,应用在很多地方,抓网页,数据分析,数据验证等,下面讲述python 导入re模块语法及规则. 1,re模块语法 re.match 从头开始匹配 re.search 匹配 ...
- 第四讲 自定义Realm来实现身份认证
1.jdbcReam已经实现了从数据库中获取用户的验证信息,但是jdbcRealm灵活性太差.如果要实现自己的一些特殊应用时,将不能支持.这时,可以通过自定义Realm来实现身份的认证功能. 2.Re ...
- CtfStudying之SSH私钥泄露
8/23/19 SSH私钥泄露 对于只是给定一个对应ip地址的靶场机器,我们需要对其进行扫描,探测其开放服务.我原来理解的渗透就是找到目标的漏洞,然后利用这些(这种)漏洞,最后拿到机器的最高权限:其实 ...