旋转子段(性质分析)
作者:互联网
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 }View Code
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 node{int 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 */View Code
标签:dian,node,子段,int,旋转,define,MAXN,include,性质 来源: https://www.cnblogs.com/Wwb123/p/11329075.html