• [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
    ",ans[i]);
    90     return 0;
    91 }
    View Code

    upd:回滚莫队真香。

  • 相关阅读:
    使用systemctl管理指定服务需要做的配置
    挖矿病毒
    灰度发布系统
    血一般的教训,请慎用insert into select
    关于程序bug的闲谈
    来自一个网络监控软件的自述
    为什么CTO、技术总监、架构师都不写代码,还这么牛逼?
    原来 Elasticsearch 还可以这么理解
    爬了20W+条猫咪交易数据,它不愧是人类团宠
    NPUCTF2020 这是什么觅🐎
  • 原文地址:https://www.cnblogs.com/hzoi2018-xuefeng/p/11333135.html
Copyright © 2020-2023  润新知