[bzoj4358]permu:莫队+线段树/回滚莫队

这道题是几天前水过去的,现在快没印象了,水一发。

首先我们看到它让求解的是最长的值域 连续段长度,很好。

然后就想到了山海经,但但是我还没有做。

然后又想到了很久以前的一次考试的T3旅馆hotel(我是用暴力直接过的QAQ),正解也是线段树。

但是我还是想不到用线段树,因为我单纯的认为当前在学莫队就只会用到莫队。

后来还是问了同学。

然后就很简单了。

我们考虑询问区间的这类操作。

一种做法是各种神仙树套树解决区间问题。

另一种骗分做法就是莫队了。

不会莫队。。出门左拐(逃

那么这道题思路就可以出来了:莫队操作,每次在值域线段树这个位置的数上位置插入“1”,删除减少“1”即可,然后直接答案就是[1,n]的最长连续段长。

如果你做过类似的线段树的题,这种东西就很简单了喂。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 const int N=5e4+5;
 8 inline int read(){
 9     int x=0,f=1;char ch=getchar();
10     while(ch<'0'||ch>'9') f=(ch=='-')?-1:1,ch=getchar();
11     while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
12     return x*f;
13 }
14 
15 int n,m,blo;
16 int col[N],bel[N],ans[N];
17 struct node{
18     int l,r,ord;
19     inline friend bool operator<(node a,node b){
20         return (bel[a.l] ^ bel[b.l]) ? bel[a.l] < bel[b.l] : ((bel[a.l] & 1) ? a.r < b.r : a.r > b.r);
21     }
22 }q[N];
23 struct Seg_Tree{
24 #define lch k<<1
25 #define rch k<<1|1
26     struct Node{
27         int lmax,rmax,mmax;
28         int len;
29     }tr[N<<2];
30     inline void Build(int k,int l,int r){
31         tr[k].len=r-l+1;
32         if(l==r) return;
33         int mid=(l+r)>>1;
34         Build(lch,l,mid);Build(rch,mid+1,r);
35     }
36     inline void up(int k){
37         tr[k].lmax=tr[lch].lmax;
38         tr[k].rmax=tr[rch].rmax;
39         if(tr[lch].lmax==tr[lch].len) tr[k].lmax+=tr[rch].lmax;
40         if(tr[rch].rmax==tr[rch].len) tr[k].rmax+=tr[lch].rmax;
41         tr[k].mmax=max(max(tr[lch].mmax,tr[rch].mmax),tr[lch].rmax+tr[rch].lmax);
42     }
43     inline void Insert(int k,int l,int r,int x){
44         if(l==x&&r==x){
45             tr[k].lmax=1;tr[k].rmax=1;tr[k].mmax=1;
46             return;
47         }
48         int mid=(l+r)>>1;
49         if(x<=mid)Insert(lch,l,mid,x);
50         else Insert(rch,mid+1,r,x);
51         up(k);
52     }
53     inline void Erase(int k,int l,int r,int x){
54         if(l==x&&r==x){
55             tr[k].lmax=0;tr[k].rmax=0;tr[k].mmax=0;
56             return;
57         }
58         int mid=(l+r)>>1;
59         if(x<=mid)Erase(lch,l,mid,x);
60         else Erase(rch,mid+1,r,x);
61         up(k);
62     }
63 }str;
64 
65 int main(){
66     n=read();
67     m=read();
68     blo=(int)sqrt(n)+1;
69     str.Build(1,1,n);
70     for(int i=1;i<=blo;++i)
71         for(int j=1;j<=blo;++j)
72         {bel[(i-1)*blo+j]=i;if((i-1)*blo+j==n) break;}
73     for(int i=1;i<=n;++i) col[i]=read();
74     for(int i=1;i<=m;++i){
75         q[i].l=read();
76         q[i].r=read();
77         q[i].ord=i;
78     }
79     sort(q+1,q+m+1);
80     register int l=q[1].l,r=q[1].r;
81     for(int i=l;i<=r;++i) str.Insert(1,1,n,col[i]);
82     for(int i=1;i<=m;++i){
83         while(r<q[i].r) str.Insert(1,1,n,col[++r]);
84         while(l>q[i].l) str.Insert(1,1,n,col[--l]);
85         while(l<q[i].l) str.Erase(1,1,n,col[l++]);
86         while(r>q[i].r) str.Erase(1,1,n,col[r--]);
87         ans[q[i].ord]=str.tr[1].mmax;
88     }
89     for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
90     return 0;
91 }
View Code

 

upd:回滚莫队真香。

posted @ 2019-08-10 21:46  _xuefeng  阅读(366)  评论(0编辑  收藏  举报