bzoj 4358 permu

  比较容易想到莫队算法+线段树,但是这样时间复杂度是O(nsqrtnlogn)无法通过,考虑如果不进行删除操作,只有添加操作的话那么并查集就可以实现了,于是可以设定sqrtn块,每个块范围为(i-1)*sqrtn到i*sqrtn,那么对于一个左端点在该块之中的询问,若右端点超过块的范围,由于右端点递增,直接添加,而询问在块中的部分则暴力添加,添加完注意还原,复杂度O(nlogn),此题想法与CF620F有一些类似。

  代码

  1 #include<cstdio>
  2 #include<algorithm>
  3 #define nc() getchar()
  4 #define N 500100
  5 #define Q 300
  6 using namespace std;
  7 int n,m,i,j,k,pos[N],ans,Ans[N],tmp,top,stack[N];
  8 inline int read(){
  9     int x=0;char ch=nc();for(;ch<'0'||ch>'9';ch=nc());
 10     for(;ch<='9'&&ch>='0';x=x*10+ch-48,ch=nc());return x;
 11 }
 12 struct g{
 13     int l,r,id;
 14 }a[N];
 15 int f[N],s[N],e[N];
 16 bool cmp(g a,g b)
 17 {
 18     if (pos[a.id]==pos[b.id])
 19     return a.r<b.r;
 20     return pos[a.id]<pos[b.id];
 21 }
 22 int gf(int x)
 23 {
 24     int p=x,t;
 25     while (p!=f[p]) p=f[p];
 26     while (x!=p) t=f[x],f[x]=p,x=t;
 27     return p;
 28 }
 29 int GF(int x){
 30     int p=x;
 31     while (p!=f[p]) p=f[p];return p;
 32 }
 33 void add(int x)
 34 {
 35     s[x]=1;
 36     int a,b;
 37     a=gf(x+1);b=gf(x-1);
 38     if (s[a]) s[a]+=s[gf(x)],f[gf(x)]=a;
 39     if (s[b]) s[b]+=s[gf(x)],f[gf(x)]=b;
 40     ans=max(ans,s[gf(x)]);
 41 }
 42 void add2(int x)
 43 {
 44     s[x]=1;
 45     int a,b;
 46     a=GF(x+1);b=GF(x-1);
 47     if (s[a]) 
 48     {
 49         s[GF(x)]+=s[a];f[a]=GF(x);
 50         top++;stack[top]=a;
 51     }
 52     if (s[b]) 
 53     {
 54         s[GF(x)]+=s[b];f[b]=GF(x);
 55         top++;stack[top]=b;
 56     }
 57     ans=max(ans,s[x]);
 58 }
 59 int main()
 60 {
 61     n=read();
 62     m=read();
 63     for (i=1;i<=n;i++)
 64         e[i]=read();
 65     for (i=1;i<=m;i++)
 66     {
 67         a[i].l=read();
 68         a[i].r=read();
 69         a[i].id=i;
 70         pos[i]=a[i].l/Q;
 71     }
 72 
 73     sort(a+1,a+1+m,cmp);
 74     for (i=1;i<=m;i++)
 75     {
 76         int cur=(a[i].l/Q+1)*Q;
 77         int now=min(n+1,cur);
 78         for (k=i;k<=m;k++) if (a[k].l/Q!=a[i].l/Q) break;
 79         int o=k;
 80         for (j=0;j<=n+1;j++) f[j]=j,s[j]=0;ans=0;
 81     
 82         for (j=i;j<o;j++)
 83         {    
 84             while (cur<=a[j].r) add(e[cur++]);
 85             tmp=ans;top=0;
 86                 
 87             for (k=a[j].l;k<=min(a[j].r,now-1);k++)
 88                 add2(e[k]);
 89             
 90             Ans[a[j].id]=ans;
 91         
 92             for (k=top;k>=1;k--) f[stack[k]]=stack[k];
 93             for (k=a[j].l;k<=min(a[j].r,now-1);k++)
 94                 s[e[k]]=0,f[e[k]]=e[k];    
 95             ans=tmp;
 96         
 97         }
 98         
 99         i=o-1;
100     }
101     
102     for (i=1;i<=m;i++)
103     printf("%d
",Ans[i]);
104 }
原文地址:https://www.cnblogs.com/fzmh/p/5388482.html