bzoj 4358: permu 莫队

  第一步先莫队分块。

  对于每一块l~r,初始右端点设为r+1,然后每个询问先将右端点往右移,然后处理询问在l~r之间的部分,最后用一个栈再把l~r的复原。

  具体来说是维护两个数组now1和now2,一个向右最长的长度,一个向左的长度,每插入一个值x,用x+1的now2更新x的now2,用x-1的now1更新x的now1,now1[x]+now2[x]-1可能为最终答案,再把x所在的最长区间的左右端点的now数组更新,中间的值不需要更新,因为不可能再往中间插入数了。

  有生以来第一次bzoj榜一。

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define N 50005
 6 #define d 223
 7 using namespace std;
 8 int n,m;
 9 int c[N];
10 int ans[N];
11 struct node
12 {
13     int l,r,id,yuan;
14     friend bool operator < (node aa,node bb)
15     {
16         if(aa.id!=bb.id)return aa.id<bb.id;
17         return aa.r<bb.r;
18     }
19 }a[N];
20 int now1[N],now2[N];
21 int st1[N*2],st2[N*2],top;
22 int main()
23 {
24     scanf("%d%d",&n,&m);
25     for(int i=1;i<=n;i++)scanf("%d",&c[i]);
26     for(int i=1;i<=m;i++)
27     {
28         scanf("%d%d",&a[i].l,&a[i].r);
29         a[i].yuan=i;a[i].id=(a[i].l-1)/d+1;
30     }
31     sort(a+1,a+m+1);
32     int as=0;int r=0,t=0;
33     for(int i=1;i<=m;i++)
34     {
35         if(a[i].id!=a[i-1].id)
36         {
37             as=0;
38             memset(now1,0,sizeof(now1));
39             memset(now2,0,sizeof(now2));
40             r=t=a[i].id*d;
41         }
42         while(a[i].r>r)
43         {
44             r++;
45             now1[c[r]]=now1[c[r]+1]+1;
46             now2[c[r]]=now2[c[r]-1]+1;
47             int tt=now1[c[r]]+now2[c[r]]-1;
48             now2[c[r]+now1[c[r]]-1]=tt;
49             now1[c[r]-now2[c[r]]+1]=tt;
50             as=max(as,tt);
51         }
52         int tmp=as;top=0;
53         for(int j=a[i].l;j<=min(a[i].r,t);j++)
54         {
55             now1[c[j]]=now1[c[j]+1]+1;
56             now2[c[j]]=now2[c[j]-1]+1;
57             int tt=now1[c[j]]+now2[c[j]]-1;
58             int rr=c[j]+now1[c[j]]-1;int ll=c[j]-now2[c[j]]+1;
59             st1[++top]=rr;st2[top]=now2[rr];
60             st1[++top]=ll;st2[top]=now1[ll];
61             now2[rr]=tt;
62             now1[ll]=tt;
63             tmp=max(tmp,tt);
64         }
65         for(int j=top;j>=1;j--)
66         {
67             if(j%2==0)now1[st1[j]]=st2[j];
68             else now2[st1[j]]=st2[j];
69         }
70         for(int j=a[i].l;j<=min(a[i].r,t);j++)
71         {
72             now1[c[j]]=now2[c[j]]=0;
73         }
74         ans[a[i].yuan]=tmp;
75     }
76     for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
77     return 0;
78 }

 

posted @ 2017-02-13 19:55  SD_le  阅读(851)  评论(0编辑  收藏  举报
重置按钮