EOJ Monthly 2019.5 (based on May Selection)-D.翻转(前缀和处理,思维考虑)

    xiaoxiao2023-10-05  149

    单点时限: 5.0 sec

    内存限制: 512 MB

    QQ小方以前不会翻转数列,现在他会了,所以他急切的想教会你。

    翻转数列指的是,把一个数列倒置。具体来说,如果一个数列是 a1,a2,a3⋯an ,那么翻转以后的数列是 a′1,a′2,a′3⋯a′n=an,an−1,an−2⋯a1 。

    单单讲给你听肯定是不够的,为了表现自己,QQ小方现在要考考你。

    现在QQ小方有一个数列 a1,a2,a3⋯an 。他想要翻转数列中的其中一个子数列(一个数列的子数列指的是任意个连续的数组成的子序列,子序列可以为空)。而且他希望在翻转以后有尽量多的位置满足 i=a′i 。QQ小方想知道,经过一次翻转操作,数列中最多能有多少位置满足 i=a′i 。

    输入格式

    输入数据第一行包含一个整数 n ( 1≤n≤5⋅106 ) ,表示数列的长度。

    接下来的一行包含 n 个用空格隔开的整数,分别表示 a1,a2,a3⋯an ( 1≤ai≤n ) ,表示初始的数列。

    输出格式

    输出一行包含一个整数,表示答案。

    样例

    Input

    4 3 4 1 2

    Output

    2

    提示

    可以选择翻转 [1,3] 子数列,变成 1,4,3,2 ,则位置 1 和 3 满足要求了。

    也可以选择翻转 [2,4] 子数列,变成 3,2,1,4 ,则位置 2 和 4 满足要求了。

    没有更优的翻转方案了。

    思路:这个题目的话,比赛的时候没做出来,当时想的是,如果他有5e6个点,全都有互相匹配的的话,就只有2.5e3个匹配点了,然后后续暴力就行了,但是但是没做出来,没考虑到那种两边的情况,一开始搞的那个最大值也是不对的,因为一开始就有放好了的,这是我昨天犯的错误,

    ---------下面是思路-----------------

    就是给出的点,有的是本来的位置就是对应的,也就是说我不给他翻转他的位置就是有贡献的,这一点要考虑到,昨天也是错误在这个地方,

    下面就是对于每一个本来位置不对应的点的处理,我们把每一个位置不对应的点处理,我们知道,每一个位置不对应的点都会产生一个可能可行的翻转区间,那么我们把这个翻转区间的翻转轴保存,翻转的两端也保存,然后处理每一个翻转轴就可以了,

    代码:

    #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<vector> using namespace std; const int maxn=5e6+10; int n; int a[maxn],pre[maxn]; struct Node //左右端点和长度 { int l,r,len; Node(){} Node(int x,int y,int z):l(x),r(y),len(z){} }; int cmp(Node a,Node b) { return a.len<b.len; } vector<Node >G[maxn*2];//长度乘二 int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pre[i]=pre[i-1]+(a[i]==i);//记录前缀的本来位置对应好了的数量 if(a[i]>i) { G[a[i]+i].push_back(Node(i,a[i],a[i]-i+1)); } else if(a[i]<i) { G[a[i]+i].push_back(Node(a[i],i,i-a[i]+1)); } else G[a[i]+i].push_back(Node(a[i],i,0)); } int maxx=pre[n]; for(int i=1;i<=2*n;i++) { sort(G[i].begin(),G[i].end(),cmp); } for(int i=1;i<=2*n;i++) { for(int j=0;j<G[i].size();j++) { Node tmp=G[i][j]; int qans=pre[n]-pre[tmp.r]+pre[tmp.l-1];//处理本来就对应好了的 qans+=(j+1);//加上在这个区间内可行的对应端点 maxx=max(maxx,qans); } } printf("%d\n",maxx); }

     

    最新回复(0)