[排序][vector] Jzoj P6288 旋转子段

Description

 

题解

  • 显然我们对于两个位置i和j,如果a[i]+i==a[j]+j,那么反转后肯定都为固定点
  • 然后我们可以枚举每个旋转点,每个点打入v[a[i]+i]
  • 我们先按照旋转区间长度先排序,然后我们发现这个点再vector中的位置,就是它内部所包含的反转过后能成为不动点的点的数目(因为比他小的都包含在里面,随着它反转必然成为不动点)
  • 还要加上一(这个点本身的贡献)这样的话,剩下的不反转的区间直接使用前缀和维护不动点个数即可

 

代码

 1 #include <vector>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 const int N=100010;
 8 vector<int>v[N*2];
 9 int n,ans,k,p,sum[N];
10 bool cmp(int x,int y) { return abs(x*2-k)<abs(y*2-k); }
11 int main()
12 {
13     freopen("rotate.in","r",stdin),freopen("rotate.out","w",stdout),scanf("%d",&n);
14     for (int i=1,x;i<=n;i++) scanf("%d",&x),v[x+i].push_back(i),sum[i]=sum[i-1]+(x==i);
15     for (int i=2;i<=n*2;i++)
16         if (!v[i].empty())
17         {
18             k=i,sort(v[i].begin(),v[i].end(),cmp),p=v[i].size();
19             for (int j=0;j<p;j++)
20             {
21                 int l=v[i][j],r=i-v[i][j];
22                 if (l>r) swap(l,r); 
23                 ans=max(ans,sum[l-1]+sum[n]-sum[r]+j+1);
24             }
25         }
26     printf("%d",ans);
27 }    

 

转载于:https://www.cnblogs.com/Comfortable/p/11329766.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值