• [bzoj4358] permu


      强行上莫队+线段树显然是会T的。

      如果莫队没有删除的转移的话...就可以用并查集代替线段树。

      所以按照一般姿势将询问排序好后,右端点照常,左端点每次从左端点所属块的末端开始跑,跑完后暴力撤回。

      复杂度还是O(m*n^0.5)

      为了能够撤回,并查集合并的时候,以临时增加的点为父亲。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 const int maxn=50233;
     8 struct zs{int l,r,id;}q[maxn];
     9 int fa[maxn],sz[maxn],mp[maxn],st[maxn],top;
    10 int B[maxn],An[maxn];
    11 int i,j,k,n,m,ans;
    12 
    13 int ra;char rx;
    14 inline int read(){
    15     rx=getchar(),ra=0;
    16     while(rx<'0'||rx>'9')rx=getchar();
    17     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
    18 }
    19 
    20 inline int getfa(int x){return fa[x]!=x?fa[x]=getfa(fa[x]):x;}
    21 inline int get1(int x){while(fa[x]!=x)x=fa[x];return x;}
    22 
    23 inline void add(int x){
    24     sz[x]=1;
    25     int pre=getfa(x-1),aft=getfa(x+1);
    26     if(sz[pre])sz[pre]+=sz[x],fa[x]=pre,x=pre;
    27     if(sz[aft])sz[aft]+=sz[x],fa[x]=aft,x=aft;
    28     if(sz[x]>ans)ans=sz[x];
    29 }
    30 inline void add2(int x){
    31     sz[x]=1;
    32     int pre=get1(x-1),aft=get1(x+1);
    33     
    34     if(sz[pre])
    35         sz[x]+=sz[pre],fa[pre]=x,st[++top]=pre;
    36     if(sz[aft])
    37         sz[x]+=sz[aft],fa[aft]=x,st[++top]=aft;
    38     if(sz[x]>ans)ans=sz[x];
    39 }
    40 
    41 bool cmp(zs a,zs b){return B[a.l]<B[b.l]||(B[a.l]==B[b.l]&&a.r<b.r);}
    42 
    43 int main(){
    44     n=read(),m=read();int kuai=(int)sqrt(n*1.2)+3;
    45     for(i=1;i<=n;i++)mp[i]=read(),B[i]=(i+kuai-1)/kuai;
    46     for(i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].id=i;
    47     sort(q+1,q+1+m,cmp);
    48     int r,r1,now,tmp;
    49     for(i=1;i<=m;){
    50         for(r=i;B[q[r].l]==B[q[i].l];r++);r--;
    51         r1=B[q[i].l]==B[n]?n:B[q[i].l]*kuai;
    52         for(j=0;j<=n+1;j++)fa[j]=j,sz[j]=0;
    53         ans=0,now=r1+1;
    54         
    55         for(j=i;j<=r;j++){
    56             while(now<=q[j].r)add(mp[now++]);
    57             tmp=ans,top=0;
    58             for(k=q[j].l;k<=q[j].r&&k<=r1;k++)add2(mp[k]);
    59             An[q[j].id]=ans;
    60             while(top)fa[st[top]]=st[top],top--;
    61             for(k=q[j].l;k<=q[j].r&&k<=r1;k++)fa[mp[k]]=mp[k],sz[mp[k]]=0;
    62             ans=tmp;
    63         }
    64         i=r+1;
    65     }
    66     for(i=1;i<=m;i++)printf("%d
    ",An[i]);
    67 }
    View Code
  • 相关阅读:
    Linux常用命令琐记
    JDK 在linux下支持epoll了
    八卦
    JDK 1.6中的并发
    关于Atomic
    关于并发程序设计(二)
    关于并发程序设计 (一)
    Herb Sutter的一些观点
    想到Exchanger N parties的一种用法
    该拒绝MSN Messager了
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5644724.html
Copyright © 2020-2023  润新知