莫队学习笔记2

前一篇:https://www.cnblogs.com/TetrisCandy/p/13775757.html

CF220B Little Elephant and Array

简单到不能再简单的莫队模板题

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=1e6+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

int n,Q,a[N],ans[N];

struct query {int l,r,id;} q[N];
int b[N],cnt[N],tot;
bool cmp(const query &x, const query &y) {
	return b[x.l]==b[y.l] ? ((b[x.l]&1) ? x.r<y.r : x.r>y.r) : b[x.l]<b[y.l];
}
void dec(int x) {
	if(a[x]>n) return;
	if(cnt[a[x]]==a[x]) tot--;
	cnt[a[x]]--;
	if(cnt[a[x]]==a[x]) tot++;
}
void inc(int x) {
	if(a[x]>n) return;
	if(cnt[a[x]]==a[x]) tot--;
	cnt[a[x]]++;
	if(cnt[a[x]]==a[x]) tot++;
}
void solve() {
	int bs=pow(n,0.5);
	rep(i,1,n) b[i]=(i-1)/bs+1;
	sort(q+1,q+Q+1,cmp);
	int l=1,r=0;
	rep(i,1,Q) {
		while(l>q[i].l) inc(--l);
		while(r<q[i].r) inc(++r);
		while(l<q[i].l) dec(l++);
		while(r>q[i].r) dec(r--);
		ans[q[i].id]=tot;
	}
	rep(i,1,Q) printf("%d
",ans[i]);
}

int main() {
	n=read(), Q=read();
	rep(i,1,n) a[i]=read();
	rep(i,1,Q) q[i].l=read(), q[i].r=read(), q[i].id=i;
	solve();
	return 0;
}

CF617E XOR and Favorite Number

区间异或和转化为两个前缀异或和的异或,于是我们只需要统计一个cnt数组即可。

#include<bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=2e6+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

int n,m,k,s[N],bs,b[N],cnt[N],tot,ans[N];

struct query {int id,l,r;} q[N];
bool cmp(const query &x,const query &y) {
	return b[x.l]==b[y.l]?x.r<y.r:x.l<y.l;
}

void inc(int x) {tot+=cnt[s[x]^k], cnt[s[x]]++;}
void dec(int x) {cnt[s[x]]--, tot-=cnt[s[x]^k];}

signed main() {
	n=read(), m=read(), k=read(), bs=pow(n,0.5);
	rep(i,1,n) s[i]=s[i-1]^read(), b[i]=(i-1)/bs+1;
	rep(i,1,m) {
		int l=read(), r=read();
		q[i]=(query){i,l-1,r};
	}
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	rep(i,1,m) {
		while(l>q[i].l) inc(--l);
		while(r<q[i].r) inc(++r);
		while(l<q[i].l) dec(l++);
		while(r>q[i].r) dec(r--);
		ans[q[i].id]=tot;
	}
	rep(i,1,m) printf("%lld
",ans[i]);
	return 0;
}

P3709 大爷的字符串题

一道简单的lxl题。首先转化一下。对于题目所求最多还剩多少rp,我们可以贪心先从小到大撸一遍,然后清空一下,然后再撸一遍。所以答案为区间众数出现次数。

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=2e5+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

int n,m,a[N],bs,b[N],cnt[N],tot[N],tans,ans[N];

struct disc {int id,val;} d[N];
bool cmp(const disc &x,const disc &y) {return x.val<y.val;}
void discrete() {
	rep(i,1,n) d[i]=(disc) {i,a[i]};
	sort(d+1,d+n+1,cmp);
	int cnt=0;
	rep(i,1,n) a[d[i].id]=(d[i].val==d[i-1].val?cnt:++cnt);;
}

struct query {int id,l,r;} q[N];
bool cmp2(const query &x,const query &y) {
	return b[x.l]==b[y.l]?((b[x.l]&1)?x.r<y.r:x.r>y.r):b[x.l]<b[y.l];
}

void inc(int x) {
	tot[cnt[a[x]]]--, tot[++cnt[a[x]]]++;
	if(cnt[a[x]]>tans) tans=cnt[a[x]];
}
void dec(int x) {
	if(cnt[a[x]]==tans&&tot[cnt[a[x]]]==1) tans=cnt[a[x]]-1;
	tot[cnt[a[x]]]--, tot[--cnt[a[x]]]++;
}

int main() {
	n=read(), m=read(), bs=pow(n,0.5);
	rep(i,1,n) a[i]=read(), b[i]=(i-1)/bs+1;
	discrete();
	rep(i,1,m) {
		int l=read(), r=read();
		q[i]=(query){i,l,r};
	}
	sort(q+1,q+m+1,cmp2);
	int l=1,r=0;
	rep(i,1,m) {
		while(l>q[i].l) inc(--l);
		while(r<q[i].r) inc(++r);
		while(l<q[i].l) dec(l++);
		while(r>q[i].r) dec(r--);
		ans[q[i].id]=-tans;
	}
	rep(i,1,m) printf("%d
",ans[i]);
	return 0;
}

莫队上树

把树转化为序列玩莫队。

SP10707 COT2 - Count on a tree II

转化为欧拉序。设第一次出现为 (s_u)。则欧拉序的 ([t_u,s_v])(u,v) 路径包含的一次,其他一些点包含了两次。两次的我们考虑抵消掉。如果 u v 不是直系路径,那么我们发现其 lca 不在路径上。那怎么办?我们直接加上 LCA 的贡献即可。通过实现把 LCA 一把算好可以做到 (O(nsqrt n))

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=1e5+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

struct edge {int to,nxt;} e[N*2]; int hd[N],tot;
void add(int u,int v) {e[++tot]=(edge){v,hd[u]};hd[u]=tot;}

int n,m,a[N],f[N][29],d[N],s[N],t[N],et[N],tick,b[N],cnt[N],mt,ans[N];
bool used[N];

struct query{int id,l,r,lca;}q[N];
bool cmp(const query &x, const query &y) {
	return b[x.l]==b[y.l] ? ((b[x.l]&1) ? x.r<y.r : x.r>y.r) : b[x.l]<b[y.l];
}
void inc(int x) {mt+=(++cnt[a[et[x]]]==1);}
void dec(int x) {mt-=(--cnt[a[et[x]]]==0);}
void c(int x) {(used[et[x]]^=1)?inc(x):dec(x);}

void dfs(int u,int fa) {
	d[u]=d[fa]+1, f[u][0]=fa, et[s[u]=++tick]=u;
	rep(h,1,20) f[u][h]=f[f[u][h-1]][h-1];
	for(int i=hd[u],v;i;i=e[i].nxt) {
		if((v=e[i].to)==fa) continue;
		dfs(v,u);
	}
	et[t[u]=++tick]=u;
}

int lca(int u,int v) {
	if(d[u]<d[v]) swap(u,v);
	per(h,20,0) if(d[f[u][h]]>=d[v]) u=f[u][h];
	if(u==v) return u;
	per(h,20,0) if(f[u][h]!=f[v][h]) u=f[u][h],v=f[v][h];
	return f[u][0];
}

struct disc{int id,val;}ds[N];
bool cmp2(const disc &x,const disc &y) {return x.val<y.val;}
void discrete() {
	rep(i,1,n) ds[i]=(disc){i,a[i]};
	sort(ds+1,ds+n+1,cmp2);
	int cn=0;
	rep(i,1,n) {
		if(ds[i].val!=ds[i-1].val) cn++;
		a[ds[i].id]=cn;
	}
}

signed main() {
	n=read(), m=read();
	rep(i,1,n) a[i]=read();
	discrete();
	int bs=pow(n,0.5);
	rep(i,1,2*n) b[i]=(i-1)/bs+1;
	rep(i,1,n-1) {
		int u=read(), v=read();
		add(u,v), add(v,u);
	}
	dfs(1,0);
	rep(i,1,m) {
		int u=read(), v=read(), l=lca(u,v);
		if(s[u]>s[v]) swap(u,v);
		if(l==u) q[i]=(query){i,s[u],s[v],0};
		else q[i]=(query){i,t[u],s[v],l};
	}
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	rep(i,1,m) {
		while(l>q[i].l) c(--l);
		while(r<q[i].r) c(++r);
		while(l<q[i].l) c(l++);
		while(r>q[i].r) c(r--);
		if(q[i].lca) c(s[q[i].lca]);
		ans[q[i].id]=mt;
		if(q[i].lca) c(s[q[i].lca]);
	}
	rep(i,1,m) printf("%d
",ans[i]);
	return 0;
} 

CF375D Tree and Queries

甚至更加简单。由于是子树问询,所以在dfs序上是一个连续完整的区间 ([s_u,t_u])

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=2e5+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

struct edge {int to,nxt;} e[N*2]; int hd[N],tot;
void add(int u,int v) {e[++tot]=(edge){v,hd[u]};hd[u]=tot;}

int n,c[N],m,bl,b[N],et[N],tick,s[N],t[N],cnt[N],sum[N],ans[N];

struct query{int id,l,r,k;}q[N];
bool cmp(const query &x,const query &y) {
	return b[x.l]==b[y.l]?x.r<y.r:b[x.l]<b[y.l];
}
void inc(int x) {cnt[c[et[x]]]++,sum[cnt[c[et[x]]]]++;}
void dec(int x) {sum[cnt[c[et[x]]]]--,cnt[c[et[x]]]--;}

void dfs(int u,int fa) {
	et[s[u]=++tick]=u;
	for(int i=hd[u],v;i;i=e[i].nxt) {
		if((v=e[i].to)==fa) continue;
		dfs(v,u);
	}
	t[u]=tick;
} 

signed main() {
	n=read(), m=read();
	rep(i,1,n) c[i]=read();
	rep(i,1,n-1) {
		int u=read(), v=read();
		add(u,v),add(v,u);
	}
	dfs(1,0);
	bl=sqrt(n);
	rep(i,1,n) b[i]=(i-1)/bl+1;
	rep(i,1,m) {
		int u=read(), k=read();
		q[i]=(query){i,s[u],t[u],k};
	}
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	rep(i,1,m) {
		while(l>q[i].l) inc(--l);
		while(r<q[i].r) inc(++r);
		while(l<q[i].l) dec(l++);
		while(r>q[i].r) dec(r--);
		ans[q[i].id]=sum[q[i].k];
	}
	rep(i,1,m) printf("%d
",ans[i]);
	return 0;
}

BITSET+莫队

前一篇已经有了一题(掉进兔子洞)。

P3674 小清新人渣的本愿

假设bitset为S,则判断是否有两个数相减为 (x) 的方法为判断 (S&(S<<x)) 是否有1。而加法则可以相反考虑。设存储 (Max_a-a) 的bitset为S2,则判断是否有两个数相加为 (x) 的方法即 (S1&(S2>>(Max_a-a)))。乘法也好做。我们可以枚举每一个约数然后判断是否存在。由于约数个数是 (sqrt a) 级别的,所以可做。

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=1e5+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

int n,m,bl,a[N],b[N],mx,cnt[N],ans[N];

struct query {int id,opt,l,r,x;} q[N];
bool cmp(const query &x,const query &y) {
	return b[x.l]==b[y.l]?((b[x.l]&1)?x.r<y.r:x.r>y.r):b[x.l]<b[y.l];
}

bitset<N>bs,ibs;
void inc(int x) {if(++cnt[a[x]]==1) bs[a[x]]=1, ibs[mx-a[x]]=1;}
void dec(int x) {if(--cnt[a[x]]==0) bs[a[x]]=0, ibs[mx-a[x]]=0;}

signed main() {
	n=read(), m=read(), bl=pow(n,0.5);
	rep(i,1,n) a[i]=read(), b[i]=(i-1)/bl+1;
	mx=100000;
	rep(i,1,m) q[i].id=i, q[i].opt=read(), q[i].l=read(), q[i].r=read(), q[i].x=read();
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	rep(i,1,m) {
		while(l>q[i].l) inc(--l);
		while(r<q[i].r) inc(++r);
		while(l<q[i].l) dec(l++);
		while(r>q[i].r) dec(r--);
		if(q[i].opt==1) ans[q[i].id]=(bs&(bs<<q[i].x)).any();
		else if(q[i].opt==2) ans[q[i].id]=(bs&(ibs>>(mx-q[i].x))).any();
		else {
			int x=q[i].x;
			rep(j,1,sqrt(x)) if(x%j==0&&bs[j]&&bs[x/j]) {ans[q[i].id]=1;break;}
		}
	}
	rep(i,1,m) puts(ans[i]?"hana":"bi");
	return 0;
}

P5355 [Ynoi2017] 由乃的玉米田

加了一个除法。考虑根号分治。(xge sqrt mx) 的时候,我们直接和乘法一样暴力枚举即可。 (xle sqrt mx) 时,我们可以 (O(sqrt x n))来算出对于每个 (x),对于每个 (r),满足 ([l,r]) 的答案为 1 的最大的 (l),设其为 (ml_r)。我们算出 (lst_{a_i}) 代表上一个 (a_i) 在哪里。然后我们递推即可。

注意特判乘法和除法 x=0 的情况

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=1e5+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

int n,m,bl,a[N],b[N],mx,cnt[N],ans[N],lst[N],ml[N];

struct query {int id,opt,l,r,x;} q[N];
bool cmp(const query &x,const query &y) {
	return b[x.l]==b[y.l]?((b[x.l]&1)?x.r<y.r:x.r>y.r):b[x.l]<b[y.l];
}

bitset<N>bs,ibs;
void inc(int x) {if(++cnt[a[x]]==1) bs[a[x]]=1, ibs[mx-a[x]]=1;}
void dec(int x) {if(--cnt[a[x]]==0) bs[a[x]]=0, ibs[mx-a[x]]=0;}

signed main() {
	n=read(), m=read(), bl=pow(n,0.5);
	rep(i,1,n) a[i]=read(), b[i]=(i-1)/bl+1;
	mx=100000;
	rep(i,1,m) q[i].id=i, q[i].opt=read(), q[i].l=read(), q[i].r=read(), q[i].x=read();
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	rep(x,1,sqrt(mx)) {
		memset(lst,0,sizeof(lst));
		memset(ml,0,sizeof(ml));
		int l=0;
		rep(r,1,n) {
			lst[a[r]]=r;
			if(a[r]*x<=mx) l=max(l,lst[a[r]*x]);
			if(a[r]%x==0) l=max(l,lst[a[r]/x]);
			ml[r]=l;
		}
		rep(i,1,m) if(q[i].opt==4&&q[i].x==x) ans[q[i].id]=(q[i].l<=ml[q[i].r]);
	}
	rep(i,1,m) {
		while(l>q[i].l) inc(--l);
		while(r<q[i].r) inc(++r);
		while(l<q[i].l) dec(l++);
		while(r>q[i].r) dec(r--);
		if(q[i].opt==1) ans[q[i].id]=(bs&(bs<<q[i].x)).any();
		else if(q[i].opt==2) ans[q[i].id]=(bs&(ibs>>(mx-q[i].x))).any();
		else if(q[i].opt==3) {
			int x=q[i].x;
			if(x!=0) {
				rep(j,1,sqrt(x)) if(x%j==0&&bs[j]&&bs[x/j]) {ans[q[i].id]=1;break;}
			}
			else ans[q[i].id]=bs[0];
		} else if(q[i].x>sqrt(mx)) {
			int x=q[i].x;
			for(int j=1;j*x<=mx;j++) if(bs[j]&&bs[j*x]) {ans[q[i].id]=1;break;}
		} else if(q[i].x==0) ans[q[i].id]=bs[0]&&(cnt[0]!=q[i].r-q[i].l+1);
	}
	rep(i,1,m) puts(ans[i]?"yuno":"yumi");
	return 0;
}

带修莫队

本质就是三维莫队。几个变化

1 query结构体还需要存这是第几个版本(第几次修改以后)

2 排序的比较函数需要改为

bool cmp(const query &x,const query &y) {
	return b[x.l]==b[y.l]?(b[x.r]==b[y.r]?x.ver<y.ver:x.r<y.r):x.l<y.l;
}

即先判断 l 的块,再判断 r 的块,然后再判断 ver

3 在4个while后面还要再加2个while检查版本是否对。如果版本过老,那么就一路while更新过去;如果版本过新,那么就一路while回退回去。

while(ver<q[i].ver) upd(++ver,i);
while(ver>q[i].ver) rev(ver--,i);

有些情况upd和rev可以并起来写。

4 块长改为 (n^{frac{2}{3}}),复杂度变为 (n^{frac{5}{3}})

P1903 [国家集训队]数颜色

模板题。这道题中upd和rev可以并起来写,因为实指上就是交换被操作序列中的元素和操作队列中的元素。详见代码

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=1e6+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

int n,m,a[N],bs,b[N],qcnt,rcnt,cnt[N],tot,ans[N];

struct query {int id,l,r,ver;} q[N];
bool cmp(const query &x,const query &y) {
	return b[x.l]==b[y.l]?(b[x.r]==b[y.r]?x.ver<y.ver:x.r<y.r):x.l<y.l;
}
struct replc {int p,col;} r[N];

void inc(int x) {tot+=(++cnt[x]==1);}
void dec(int x) {tot-=(--cnt[x]==0);}
void mdf(int ver,int i) {
	if(q[i].l<=r[ver].p&&r[ver].p<=q[i].r)
		inc(r[ver].col), dec(a[r[ver].p]);
	swap(a[r[ver].p],r[ver].col);
}

int main() {
	n=read(), m=read(), bs=pow(n,0.66);
	rep(i,1,n) a[i]=read(), b[i]=(i-1)/bs+1;
	rep(i,1,m) {
		char c[3]; scanf("%s",c);
		int l=read(), rr=read();
		if(c[0]=='Q') q[++qcnt]=(query){qcnt,l,rr,rcnt};
		else r[++rcnt]=(replc){l,rr};
	}
	sort(q+1,q+qcnt+1,cmp);
	int l=1,r=0,ver=0;
	rep(i,1,m) {
		while(l>q[i].l) inc(a[--l]);
		while(r<q[i].r) inc(a[++r]);
		while(l<q[i].l) dec(a[l++]);
		while(r>q[i].r) dec(a[r--]);
		while(ver<q[i].ver) mdf(++ver,i);
		while(ver>q[i].ver) mdf(ver--,i);
		ans[q[i].id]=tot;
	}
	rep(i,1,qcnt) printf("%d
",ans[i]);
	return 0;
}

CF940F Machine Learning

注意到这道题mex可以暴力计算,因为mex不会超过 (sqrt n)。证明:如果mex为 (x),那么就存在出现 (1,2,...,x-1) 次的数,满足 (1+2+...+(x-1)le n),所以必然是 (sqrt n) 级别的。

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define per(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int N=2e5+9;

inline int read() {
    register int x=0, f=1; register char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
    return x*f;
}

int n,m,a[N],bs,b[N],qcnt,ccnt,cnt[N],tot[N],ans[N];

struct disc {int id,val;} d[N];
bool cmp(const disc &x,const disc &y) {return x.val<y.val;}
void discrete() {
	rep(i,1,n+ccnt) d[i]=(disc){i,a[i]};
	sort(d+1,d+n+ccnt+1,cmp);
	int cnt=0;
	rep(i,1,n+ccnt) a[d[i].id]=(d[i].val==d[i-1].val?cnt:++cnt);
}

struct query {int id,l,r,ver;} q[N];
struct change {int p,val;} c[N];
bool cmp2(const query &x,const query &y) {
	return b[x.l]==b[y.l]?(b[x.r]==b[y.r]?x.ver<y.ver:x.r<y.r):x.l<y.l;
}

void inc(int x) {tot[cnt[a[x]]]--,tot[++cnt[a[x]]]++;}
void dec(int x) {tot[cnt[a[x]]]--,tot[--cnt[a[x]]]++;}
void mdf(int x,int i) {
	if(q[i].l<=c[x].p&&c[x].p<=q[i].r) {
		dec(c[x].p), swap(c[x].val,a[c[x].p]), inc(c[x].p);
	} else swap(c[x].val,a[c[x].p]);
}

int main() {
	n=read(), m=read(), bs=pow(n,0.66);
	rep(i,1,n) a[i]=read(), b[i]=(i-1)/bs+1;
	rep(i,1,m) {
		int opt=read(), x=read(), y=read();
		if(opt==1) q[++qcnt]=(query){qcnt,x,y,ccnt};
		else c[++ccnt]=(change){x,y};
	}
	rep(i,1,ccnt) a[n+i]=c[i].val;
	discrete();
	rep(i,1,ccnt) c[i].val=a[n+i];
	sort(q+1,q+qcnt+1,cmp2);
	int l=1,r=0,ver=0;
	rep(i,1,qcnt) {
		while(l>q[i].l) inc(--l);
		while(r<q[i].r) inc(++r);
		while(l<q[i].l) dec(l++);
		while(r>q[i].r) dec(r--);
		while(ver<q[i].ver) mdf(++ver,i);
		while(ver>q[i].ver) mdf(ver--,i);
		ans[q[i].id]=1;
		while(tot[ans[q[i].id]]) ans[q[i].id]++;
	}
	rep(i,1,qcnt) printf("%d
",ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/TetrisCandy/p/14274579.html