原来莫队与分块没关系啊.....
安利好的博客:莫队入门详解
嗯,莫队就是采用了分块的思想,然后用指针暴力跳....
对于普通的莫队,比较玄学的就是奇偶性排序比较玄学...
//不等,不问,不犹豫,不回头. #include<bits/stdc++.h> #define _ 0 #define db double #define RE register #define ll long long #define P 1000000007 #define INF 1000000000 #define get(x) x=read() #define PLI pair<ll,int> #define PII pair<int,int> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define pb(x) push_back(x) #define ull unsigned long long #define putl(x) printf("%lld ",x) #define rep(i,x,y) for(RE int i=x;i<=y;++i) #define fep(i,x,y) for(RE int i=x;i>=y;--i) #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y) using namespace std; const int N=30010,M=1e6+10; int a[N],n,Q,now,cnt[M],belong[N],block,num,c[M]; struct wy{int l,r,id;}q[M]; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { int x=0,ff=1; char ch=getc(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getc();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getc();} return x*ff; } inline int put(int x) { if(x<0) putchar('-'),x=-x; if(x/10) put(x/10); putchar(x%10+'0'); } inline void build() { block=sqrt(n);num=n/block; if(n%block) num++; rep(i,1,n) belong[i]=(i-1)/block+1; } inline bool cmp(wy a,wy b) { return belong[a.l]!=belong[b.l]?belong[a.l]<belong[b.l]:(belong[a.l]&1?a.r<b.r:a.r>b.r); } int main() { //freopen("1.in","r",stdin); get(n); rep(i,1,n) get(a[i]); build();get(Q); rep(i,1,Q) { q[i].id=i; get(q[i].l);get(q[i].r); } sort(q+1,q+Q+1,cmp); int l=1,r=0,now=0; rep(i,1,Q) { int ql=q[i].l,qr=q[i].r; while(l<ql) now-=!--cnt[a[l++]]; while(l>ql) now+=!cnt[a[--l]]++; while(r<qr) now+=!cnt[a[++r]]++; while(r>qr) now-=!--cnt[a[r--]]; c[q[i].id]=now; } rep(i,1,Q) put(c[i]),putchar(' '); return (0^_^0); } //以吾之血,祭吾最后的亡魂
带修莫队,记得将块长定义为n^(2/3)次方,这样他的复杂度就成了n(5/3).暴力跳time就行了.
//不等,不问,不犹豫,不回头. #include<bits/stdc++.h> #define _ 0 #define db double #define RE register #define ll long long #define P 1000000007 #define INF 1000000000 #define get(x) x=read() #define PII pair<int,int> #define PLI pair<ll,int> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define pb(x) push_back(x) #define ull unsigned long long #define put(x) printf("%d ",x) #define putl(x) printf("%lld ",x) #define rep(i,x,y) for(RE int i=x;i<=y;++i) #define fep(i,x,y) for(RE int i=x;i>=y;--i) #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y) using namespace std; const int N=140000,M=1e6+10; int a[N],n,m,c[N],cnt[M],belong[N],block; struct wy{int l,r,time,id;}q[N]; struct jl{int pos,color;}b[N]; char ch[10]; inline int read() { int x=0,ff=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*ff; } inline void build() { block=pow(n,2.0/3.0); rep(i,1,n) belong[i]=(i-1)/block+1; } inline bool cmp(wy a,wy b) { return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:((belong[a.r]^belong[b.r])?belong[a.r]<belong[b.r]:a.time<b.time); } int main() { //freopen("1.in","r",stdin); get(n);get(m); rep(i,1,n) get(a[i]); build(); int cntq=0,cntc=0; rep(i,1,m) { scanf("%s",ch); if(ch[0]=='Q') { get(q[++cntq].l); get(q[cntq].r); q[cntq].time=cntc; q[cntq].id=cntq; } else { get(b[++cntc].pos); get(b[cntc].color); } } sort(q+1,q+cntq+1,cmp); int l=1,r=0,time=0,now=0; rep(i,1,cntq) { int ql=q[i].l,qr=q[i].r,qt=q[i].time; while(l<ql)now-=!--cnt[a[l++]]; while(l>ql)now+=!cnt[a[--l]]++; while(r<qr)now+=!cnt[a[++r]]++; while(r>qr)now-=!--cnt[a[r--]]; while(time<qt) { time++; if(b[time].pos>=ql&&b[time].pos<=qr) now-=!--cnt[a[b[time].pos]]-!cnt[b[time].color]++; swap(a[b[time].pos],b[time].color); } while(time>qt) { if(b[time].pos>=ql&&b[time].pos<=qr) now-=!--cnt[a[b[time].pos]]-!cnt[b[time].color]++; swap(a[b[time].pos],b[time].color); --time; } c[q[i].id]=now; } rep(i,1,cntq) put(c[i]); return (0^_^0); } //以吾之血,祭吾最后的亡魂
树上莫队,考虑欧拉序的话,遇见第二次直接删掉,第一次加入的原则,特判下lca就行了.
//不等,不问,不犹豫,不回头. #include<bits/stdc++.h> #define _ 0 #define db double #define RE register #define ll long long #define P 1000000007 #define INF 1000000000 #define get(x) x=read() #define PLI pair<ll,int> #define PII pair<int,int> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define pb(x) push_back(x) #define ull unsigned long long #define put(x) printf("%d ",x) #define putl(x) printf("%lld ",x) #define rep(i,x,y) for(RE int i=x;i<=y;++i) #define fep(i,x,y) for(RE int i=x;i>=y;--i) #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y) using namespace std; const int N=40010,M=1e5+10; int link[N],tot,n,m,b[N],d[N],ct,ou[N<<1],num,first[N],last[N],f[N][25],deep[N]; int cnt[N],vis[N],c[M],belong[N],block,now; struct edge{int y,next;}a[N<<1]; struct wy{int l,r,id,lc;}q[M]; inline int read() { int x=0,ff=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*ff; } inline int find(int x){return lower_bound(b+1,b+ct+1,x)-b;} inline void add(int x,int y) { a[++tot].y=y;a[tot].next=link[x];link[x]=tot; a[++tot].y=x;a[tot].next=link[y];link[y]=tot; } inline void dfs(int x,int fa) { ou[++num]=x;first[x]=num; go(x) { if(y==fa) continue; deep[y]=deep[x]+1; f[y][0]=x; rep(j,1,20) f[y][j]=f[f[y][j-1]][j-1]; dfs(y,x); } ou[++num]=x;last[x]=num; } inline int lca(int a,int b) { if(deep[a]>deep[b]) swap(a,b); fep(i,20,0) if(deep[f[b][i]]>=deep[a]) b=f[b][i]; if(a==b) return a; fep(i,20,0) if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i]; return f[a][0]; } inline bool cmp(wy a,wy b) { return (belong[a.l]^belong[b.l]?belong[a.l]<belong[b.l]:(belong[a.l]&1?a.r<b.r:a.r>b.r)); } inline void work(int x) { if(vis[x]){cnt[d[x]]--;if(!cnt[d[x]]) now--;} else{if(!cnt[d[x]]) now++;cnt[d[x]]++;} vis[x]^=1; } inline void build() { block=sqrt(n<<1); rep(i,1,n<<1) belong[i]=(i-1)/block+1; } int main() { //freopen("1.in","r",stdin); get(n);get(m); build(); rep(i,1,n) get(d[i]),b[i]=d[i]; sort(b+1,b+n+1); ct=unique(b+1,b+n+1)-b-1; rep(i,1,n-1) { int get(x),get(y); add(x,y); } deep[1]=1;dfs(1,0); rep(i,1,m) { int get(l),get(r),lc=lca(l,r); if(first[l]>first[r]) swap(l,r); if(lc==l) { q[i].l=first[l]; q[i].r=first[r]; } else { q[i].l=last[l]; q[i].r=first[r]; q[i].lc=lc; } q[i].id=i; } sort(q+1,q+m+1,cmp); int l=1,r=0; rep(i,1,m) { int ql=q[i].l,qr=q[i].r,lc=q[i].lc; while(l<ql) work(ou[l++]); while(l>ql) work(ou[--l]); while(r<qr) work(ou[++r]); while(r>qr) work(ou[r--]); if(lc) work(lc); c[q[i].id]=now; if(lc) work(lc); } rep(i,1,m) put(c[i]); return (0^_^0); } //以吾之血,祭吾最后的亡魂
回滚莫队,算是最妙的一种莫队,常数最小,考虑属于同一块的左端点,其右端点单调递增,每此暴力跳r指针,然后每个询问将l指针清空即可.所以只需要考虑增加的问题即可.
//不等,不问,不犹豫,不回头. #include<bits/stdc++.h> #define _ 0 #define db double #define RE register #define ll long long #define P 1000000007 #define INF 1000000000 #define get(x) x=read() #define PLI pair<ll,int> #define PII pair<int,int> #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define pb(x) push_back(x) #define ull unsigned long long #define put(x) printf("%d ",x) #define putl(x) printf("%lld ",x) #define rep(i,x,y) for(RE int i=x;i<=y;++i) #define fep(i,x,y) for(RE int i=x;i>=y;--i) #define go(x) for(int i=link[x],y=a[i].y;i;y=a[i=a[i].next].y) using namespace std; const int N=1e5+10; int n,Q,a[N],num,cnt1[N],cnt2[N]; int block,bnum,belong[N],bl[N],br[N]; ll c[N],b[N]; struct wy{int l,r,id;}q[N]; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { int x=0,ff=1; char ch=getc(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getc();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getc();} return x*ff; } inline int find(int x) {return lower_bound(b+1,b+num+1,x)-b;} inline void build() { block=sqrt(n);bnum=n/block; if(n%block) bnum++; rep(i,1,n) belong[i]=(i-1)/block+1; rep(i,1,bnum) bl[i]=(i-1)*block+1,br[i]=i*block; br[bnum]=n; } inline bool cmp(wy a,wy b) { return (belong[a.l]^belong[b.l])?belong[a.l]<belong[b.l]:a.r<b.r; } int main() { //freopen("1.in","r",stdin); get(n);get(Q); rep(i,1,n) get(a[i]),b[i]=a[i]; sort(b+1,b+n+1); num=unique(b+1,b+n+1)-b-1; rep(i,1,n) a[i]=find(a[i]); build(); rep(i,1,Q) { get(q[i].l);get(q[i].r); q[i].id=i; } sort(q+1,q+Q+1,cmp); int i=1; rep(j,1,bnum)//枚举每一块. { int l=br[j]+1,r=br[j]; ll now=0; memset(cnt1,0,sizeof(cnt1)); for(;i<=Q&&belong[q[i].l]==j;++i)//枚举这个块里的所有左端点. { ll temp; int ql=q[i].l,qr=q[i].r; if(belong[qr]==belong[ql]) { temp=0; rep(k,ql,qr) cnt2[a[k]]=0; rep(k,ql,qr) {++cnt2[a[k]];temp=max(temp,b[a[k]]*cnt2[a[k]]);} c[q[i].id]=temp;continue; } while(r<qr) {++r;++cnt1[a[r]];now=max(now,b[a[r]]*cnt1[a[r]]);} temp=now; while(l>ql) {--l;++cnt1[a[l]];now=max(now,b[a[l]]*cnt1[a[l]]);} c[q[i].id]=now; while(l<br[j]+1) {--cnt1[a[l]];++l;} now=temp; } } rep(i,1,Q) putl(c[i]); return (0^_^0); } //以吾之血,祭吾最后的亡魂