其他分享
首页 > 其他分享> > 旋转子段(性质分析)

旋转子段(性质分析)

作者:互联网

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