考前继续颓废,由于想跑路,所以这套题的题解无比草率,慎读,别说我,我是个标准颓狗了
考场打了个$O(n^2)$的暴力,成功水到70分,由于数据范围是假的,所以被干掉了15分,正解很优秀,要用到其他人正常$O(n^2)$旋转中心的思路,我这么说当时是因为我的$O(n^2)$很清奇咯,我们很容易知道对于一个旋转区间,如果他的两个端点被翻转之后都不能变为固定点,那我们完全可以缩小区间范围,毕竟翻转区间越长,你破坏原本固定点的概率越大,所以我们从头到尾先扫一遍,记录可以使这个点翻转之后成为固定点的区间,把旋转中心是同一个的扔进同一个$vector$中,由于旋转中心是$\frac{l+r}{2}$,不是整数不可做的样子,所以我们就不除2了,一样的用,其实事实上每个$vector$的$size$代表了区间个数,我们可以翻一个,翻两个,翻$size$个,所以说,我们按区间长度由小到大让元素有序,枚举$size$时候的贡献就是$sum[n]-(sum[r]-sum[l-1])+j+1$,$sum[i]$代表前$i$个点中固定点的个数,对所有的贡献取$\max$既可
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<algorithm> 5 #define maxn 500100 6 using namespace std; 7 struct node{ 8 int num,pos; 9 }a[maxn]; 10 bool operator < (const node &a,const node &b) 11 { 12 return (a.pos-a.num)<(b.pos-b.num); 13 } 14 int n,ans; 15 int sum[maxn]; 16 vector <node> b[maxn*2]; 17 int main() 18 { 19 scanf("%d",&n); 20 for(int i=1;i<=n;++i) 21 { 22 scanf("%d",&a[i].num); a[i].pos=i; 23 if(a[i].num>a[i].pos) swap(a[i].num,a[i].pos); 24 if(a[i].num==a[i].pos) sum[i]++; 25 sum[i]+=sum[i-1]; b[a[i].num+a[i].pos].push_back(a[i]); 26 } 27 for(int i=1;i<=2*n;++i) sort(b[i].begin(),b[i].end()); 28 for(int i=1;i<=2*n;++i) 29 for(int j=0;j<b[i].size();++j) 30 { 31 int da=sum[n]-(sum[b[i][j].pos]-sum[b[i][j].num-1])+j+1; 32 ans=max(da,ans); 33 } 34 printf("%d\n",ans); 35 return 0; 36 }