标签:word 计算 思考 题解 翻转 value str index x11
某个小朋友要题解,那我也就发一份吧(反正自己又一次翻车了 QAQ)
T1题目大意是给你一个数列,你能将其中的一段区间翻转,要求这个区间翻转后,整个数列的数在自己位子上的数最多,例如数字1在1位置上,求这个区间两端元素。(n<=500000)
这道题第一眼就可以看出是一题贪心,枚举每个点或不翻转,肯定是不行的。
那我们通过思考,发现将这个区间一定将某些数翻转到它应该在的位置上,于是可以计算出每个点若是将它翻转到自己应该在的位置所依靠的对称中心
我们对每个翻转中心计数即可,但是发现翻转一个区间后可能会使得一些原来有序的数改变位置,也就是说只要使得序列的扩张是从小到大的(好像说不清楚啊QAQ)
所以根据每一个点我们计算出将它翻转到自己应该在的位置的翻转中心,之后先根据翻转中心排序(这里可能会出现翻转中心在两数之间所以我们不对它除以2)
对于相同的翻转中心我们根据它的区间长度从小到大排序,使得区间从小到大扩张,因为这个区间一定是从上一个更小的区间扩张而来的,所以我们可以直接统计该区间内的价值,
对于区间之外的可以直接前缀和处理
代码在此(风格诡异,敬请谅解)
vari,j,ans,k,max,l1,mid,n,k1,k2:longint; lw,a,w,sum,last,s:array[0..5000000] of longint; procedure sort1(l,r: longint); var i,j,x,y: longint; begin i:=l; j:=r; x:=lw[(l+r) div 2]; repeat while lw[i]<x do inc(i); while x<lw[j] do dec(j); if not(i>j) then begin y:=lw[i]; lw[i]:=lw[j]; lw[j]:=y; y:=a[i]; a[i]:=a[j]; a[j]:=y; y:=w[i]; w[i]:=w[j]; w[j]:=y; inc(i); j:=j-1; end; until i>j; if l<j then sort1(l,j); if i<r then sort1(i,r); end; procedure sort(l,r: longint); var i,j,x,y: longint; begin i:=l; j:=r; x:=w[(l+r) div 2]; repeat while w[i]<x do inc(i); while x<w[j] do dec(j); if not(i>j) then begin y:=a[i]; a[i]:=a[j]; a[j]:=y; y:=w[i]; w[i]:=w[j]; w[j]:=y; y:=lw[i]; lw[i]:=lw[j]; lw[j]:=y; inc(i); j:=j-1; end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; procedure gg; var i:longint; begin for i:=1 to n do begin sum[i]:=sum[i-1]; if a[i]=i then sum[i]:=sum[i]+1; end; for i:=n downto 1 do begin last[i]:=last[i+1]; if a[i]=i then last[i]:=last[i]+1; end; end; begin readln(n); for i:=1 to n do begin read(a[i]); mid:=i+a[i]; if a[i]<=i then lw[i]:=a[i] else lw[i]:=i; w[i]:=mid; s[i]:=a[i]; end; gg; sort(1,n); i:=1; l1:=0; while i<=n do begin inc(l1); if (w[i]<>w[i+l1]) or (i+l1>n) then begin sort1(i,i+l1-1); ans:=0; // writeln(i,‘ ‘,i+l1-1); for j:=i+l1-1 downto i do begin ans:=ans+1; //writeln(j,‘ ‘,ans); if ans+sum[lw[j]-1]+last[w[j]-lw[j]+1]>max then begin max:=ans+sum[lw[j]-1]+last[w[j]-lw[j]+1]; k1:=lw[j]; k2:=w[j]; end; end; i:=i+l1; l1:=0; end; end; {writeln; for i:=1 to n do begin writeln(a[i],‘ ‘,lw[i],‘ ‘,w[i],‘ ‘,sum[i],‘ ‘,i); end;} writeln(s[k1],‘ ‘,s[k2-k1]); end. 标签:word 计算 思考 题解 翻转 value str index x11
原文地址:https://www.cnblogs.com/by-w/p/9612488.html