[排序][vector] Jzoj P6288 旋转子段
作者:互联网
题解
- 显然我们对于两个位置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 }
标签:Jzoj,int,反转,sum,子段,不动点,vector,ans,include 来源: https://www.cnblogs.com/Comfortable/p/11329766.html