旋转子段(性质分析)
Posted wwb123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了旋转子段(性质分析)相关的知识,希望对你有一定的参考价值。
60分
n^2的暴力很显然嘛........
枚举每个固定点,用个指针向区间两边扫
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<string> 7 #include<map> 8 #include<vector> 9 #define MAXN 100000 10 using namespace std; 11 int n;int sum;int a[MAXN]; 12 int biao[MAXN]; 13 int read() 14 15 int x=0;char c=getchar(); 16 while(c<‘0‘||c>‘9‘)c=getchar(); 17 while(c>=‘0‘&&c<=‘9‘) 18 19 x=(x<<1)+(x<<3)+(c^48); 20 c=getchar(); 21 22 return x; 23 24 int maxn; 25 int main() 26 27 n=read(); 28 for(int i=1;i<=n;++i) 29 30 a[i]=read(); 31 if(a[i]==i) 32 33 sum++; 34 biao[i]=1; 35 36 37 maxn=sum; 38 for(int i=1;i<=n;++i) 39 40 int point_l=i-1;int point_r=i+1;int sum_me=sum; 41 while(a[point_l]!=0&&a[point_r]!=0) 42 43 if(biao[point_l])sum_me--; 44 if(biao[point_r])sum_me--; 45 swap(a[point_l],a[point_r]); 46 if(a[point_l]==point_l)sum_me++; 47 if(a[point_r]==point_r)sum_me++; 48 maxn=max(sum_me,maxn); 49 swap(a[point_l],a[point_r]); 50 //printf("point_l=%d point_r=%d sum_me=%d\n",point_l,point_r,sum_me); 51 point_l--;point_r++; 52 53 point_l=i;point_r=i+1;sum_me=sum; 54 while(a[point_l]!=0&&a[point_r]!=0) 55 56 if(biao[point_l])sum_me--; 57 if(biao[point_r])sum_me--; 58 swap(a[point_l],a[point_r]); 59 if(a[point_l]==point_l)sum_me++; 60 if(a[point_r]==point_r)sum_me++; 61 maxn=max(sum_me,maxn); 62 swap(a[point_l],a[point_r]); 63 //printf("---point_l=%d point_r=%d sum_me=%d\n",point_l,point_r,sum_me); 64 point_l--;point_r++; 65 66 67 printf("%d\n",maxn); 68
100分n*log(n)
假设有个点位置为i权值为a[i]
那么显然它想要作出贡献只能是以(i+a[i])/2为旋转点
那么我们发现,假设我们排序一边(以固定点为关键字),
然后就我们发现(对于同一旋转点)假设从一个区间较小->区间较大,
贡献值的变化只有旋转后,变回相应位置的点,贡献++
同时会有一部分点原来是i==a[i],这些点的贡献减去,前缀和处理
1 //性质::区间的外围一定是可作出贡献点 2 //排序后每次可贡献点++,固定点-- 3 #include<cstdio> 4 #include<iostream> 5 #include<cmath> 6 #include<algorithm> 7 #include<cstring> 8 #include<string> 9 #include<map> 10 #include<vector> 11 #define MAXN 500000 12 #define ps push_back 13 #define int long long 14 using namespace std; 15 struct nodeint l,r,dian,len;e1[MAXN],e2[MAXN]; 16 int a[MAXN]; 17 int sum[MAXN],biao[MAXN]; 18 int n,maxn; 19 bool cmp(const node &a,const node &b) 20 21 return (a.dian==b.dian)?(a.len<b.len):(a.dian<b.dian); 22 23 signed main() 24 25 scanf("%lld",&n); 26 for(int i=1;i<=n;++i) 27 28 scanf("%lld",&a[i]); 29 sum[i]=sum[i-1]; 30 if(a[i]==i) 31 32 biao[i]++; 33 sum[i]++; 34 35 36 int tot1=0,tot2=0; 37 for(int i=1;i<=n;++i) 38 39 if((i+a[i])%2==0) 40 41 int zh=(i+a[i])/2; 42 e1[++tot1].l=min(i,a[i]); 43 e1[tot1].r=max(i,a[i]); 44 e1[tot1].dian=zh; 45 e1[tot1].len=abs(a[i]-i)+1; 46 //printf("e[%lld].dian=%lld %lld %lld\n",tot1,e1[tot1].dian,e1[tot1].l,e1[tot1].r); 47 48 else 49 50 int zh=(i+a[i])/2; 51 e2[++tot2].l=min(i,a[i]); 52 e2[tot2].r=max(i,a[i]); 53 e2[tot2].dian=zh; 54 e2[tot2].len=abs(a[i]-i)+1; 55 56 57 sort(e1+1,e1+tot1+1,cmp); 58 sort(e2+1,e2+tot2+1,cmp); 59 /* for(int i=1;i<=tot1;i++) 60 61 62 */ 63 int sum1=0; 64 for(int i=1;i<=tot1;++i) 65 66 //printf("i===%lld\n",i); 67 //printf("e[%lld].dian=%lld %lld %lld %lld\n",i,e1[i].dian,e1[i].l,e1[i].r,e1[i].len); 68 int l,r; 69 if(e1[i].dian==e1[i-1].dian) 70 71 //printf("case 1:\n"); 72 if(e1[i].len==e1[i-1].len)continue; 73 l=e1[i].l;r=e1[i].r; 74 int last_l=e1[i-1].l;int last_r=e1[i-1].r; 75 if(a[l]==r)sum1++;if(a[r]==l)sum1++; 76 sum1-=sum[last_l-1]-sum[l]; 77 sum1-=sum[r-1]-sum[last_r]; 78 maxn=max(maxn,sum1); 79 //printf("sum1=%lld \n",sum1); 80 81 else 82 83 l=e1[i].l;r=e1[i].r; 84 sum1=0; 85 sum1+=sum[e1[i].l-1]; 86 sum1+=sum[n]-sum[e1[i].r]; 87 if(biao[e1[i].dian]==1)sum1++; 88 maxn=max(maxn,sum1); 89 if(l==r)continue; 90 if(a[l]==r)sum1++; 91 if(a[r]==l)sum1++; 92 //printf("l=%lld r=%lld sum1=%lld\n",l,r,sum1); 93 maxn=max(maxn,sum1); 94 95 96 97 for(int i=1;i<=tot2;++i) 98 99 int l=0,r=0; 100 //printf("i=%lld\n",i); 101 // //printf("e[%lld].dian=%lld %lld %lld %lld\n",i,e2[i].dian,e2[i].l,e2[i].r,e2[i].len); 102 if(e2[i].dian==e2[i-1].dian) 103 104 if(e2[i].len==e2[i-1].len)continue; 105 l=e2[i].l;r=e2[i].r; 106 int last_l=e2[i-1].l,last_r=e2[i-1].r; 107 if(a[l]==r)sum1++;if(a[r]==l)sum1++; 108 // printf("sum1=%lld\n",sum,a[l],r); 109 sum1-=sum[last_l-1]-sum[l]; 110 sum1-=sum[r-1]-sum[last_r]; 111 maxn=max(maxn,sum1); 112 //printf("case 1sum=%lld \n",sum1); 113 114 else 115 116 l=e2[i].l;r=e2[i].r;sum1=0; 117 if(a[l]==r)sum1++; 118 if(a[r]==l)sum1++; 119 sum1+=sum[l-1]; 120 sum1+=sum[n]-sum[r]; 121 maxn=max(maxn,sum1); 122 // printf("l=%lld r=%lld sum1=%lld\n",l,r,sum1); 123 124 125 printf("%lld\n",maxn); 126 127 /* 128 8 129 2 3 4 1 5 7 8 6 130 */
以上是关于旋转子段(性质分析)的主要内容,如果未能解决你的问题,请参考以下文章