[学习笔记]树上莫队

其实树上莫队是一个欧拉序而已嘛,像普通的莫队,特判一下出现过两次的值就行了

\(st_i\)\(i\) 进栈的时间,\(ed_i\)\(i\) 出栈的时间,\(dfn_x<dfn_y\) ,那么就可以分两种情况:

1、\(y\)\(x\) 子树中,也就是 \(LCA(x,y)=x\),那么区间转化成 \([st_x,st_y]\)

2、\(y\) 不在 \(x\) 子树中,也就是 \(LCA(x,y)\not =x\),那么区间转化成 \([ed_x,st_y]\)

然后就是板子了

for(int i=1;i<=m;i++){
    x=read(),y=read();
    q[i].anc=LCA(x,y);q[i].id=i;
    if(x==q[i].anc||y==q[i].anc){
        q[i].anc=0;q[i].l=st[x];q[i].r=st[y];
        if(q[i].l>q[i].r) q[i].l=st[y],q[i].r=st[x];
    }
    else {
        q[i].l=ed[x];q[i].r=st[y];
        if(q[i].l>q[i].r) q[i].l=ed[y],q[i].r=st[x];
    }
}

1、SP10707 COT2 - Count on a tree II

其实我国庆的时候就学了,只不过我一直 \(WA\)...后来从倍增换成树剖,重构一遍代码就 \(A\)

\(Code\ Below:\)

#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn],vis[maxn],cnt[maxn],ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];

struct Query{
    int l,r,anc,id;
}q[maxn];

bool cmp(Query a,Query b){
    if((a.l-1)/blo!=(b.l-1)/blo)
        return (a.l-1)/blo<(b.l-1)/blo;
    return a.r<b.r;
}

inline int read(){
    register int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return (f==1)?x:-x;
}
inline void add(int x,int y){
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}

void dfs1(int x,int f){
    siz[x]=1;fa[x]=f;
    dep[x]=dep[f]+1;
    st[x]=++tim;p[tim]=x;
    int maxson=-1;
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];
        if(y==f) continue;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(maxson<siz[y]){
            maxson=siz[y];
            son[x]=y;
        }
    }
    ed[x]=++tim;p[tim]=x;
}

void dfs2(int x,int topf){
    top[x]=topf;
    if(son[x]) dfs2(son[x],topf);
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}

int LCA(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    return x;
}

int update(int x){
    if(vis[x]){
        if(--cnt[a[x]]==0) now--;
    }
    else if(++cnt[a[x]]==1) now++;
    vis[x]^=1;
}

int main()
{
    n=read(),m=read();blo=sqrt(n);
    for(int i=1;i<=n;i++) mp[i]=a[i]=read();
    sort(mp+1,mp+n+1);
    int t=unique(mp+1,mp+n+1)-mp-1;
    for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1,mp+t+1,a[i])-mp;
    int x,y;
    for(int i=1;i<n;i++){
        x=read(),y=read();
        add(x,y);add(y,x);
    }
    dfs1(1,0);dfs2(1,1);
    for(int i=1;i<=m;i++){
        x=read(),y=read();
        q[i].anc=LCA(x,y);q[i].id=i;
        if(x==q[i].anc||y==q[i].anc){
            q[i].anc=0;q[i].l=st[x];q[i].r=st[y];
            if(q[i].l>q[i].r) q[i].l=st[y],q[i].r=st[x];
        }
        else {
            q[i].l=ed[x];q[i].r=st[y];
            if(q[i].l>q[i].r) q[i].l=ed[y],q[i].r=st[x];
        }
    }
    sort(q+1,q+m+1,cmp);
    int L=1,R=0;
    for(int i=1;i<=m;i++){
        while(R<q[i].r) update(p[++R]);
        while(R>q[i].r) update(p[R--]);
        while(L<q[i].l) update(p[L++]);
        while(L>q[i].l) update(p[--L]);
        if(q[i].anc) update(q[i].anc);
        ans[q[i].id]=now;
        if(q[i].anc) update(q[i].anc);
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

2、苹果树(本地Cena自测)

其实就是特判一下 \(cnt_a\)\(cnt_b\)

只不过我非常傻,离散了一下颜色,就 \(GG\)

\(Code\ Below:\)

#include <cstdio>
#include <cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn],vis[maxn],cnt[maxn],ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];

struct Query{
	int l,r,a,b,anc,id;
}q[maxn];

bool cmp(Query a,Query b){
	if((a.l-1)/blo!=(b.l-1)/blo)
		return (a.l-1)/blo<(b.l-1)/blo;
	return a.r<b.r;
}

inline int read(){
	register int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return (f==1)?x:-x;
}
inline void add(int x,int y){
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}

void dfs1(int x,int f){
	siz[x]=1;fa[x]=f;
	dep[x]=dep[f]+1;
	st[x]=++tim;p[tim]=x;
	int maxson=-1;
	for(int i=head[x],y;i;i=nxt[i]){
		y=to[i];
		if(y==f) continue;
		dfs1(y,x);
		siz[x]+=siz[y];
		if(maxson<siz[y]){
			maxson=siz[y];
			son[x]=y;
		}
	}
	ed[x]=++tim;p[tim]=x;
}

void dfs2(int x,int topf){
	top[x]=topf;
	if(son[x]) dfs2(son[x],topf);
	for(int i=head[x],y;i;i=nxt[i]){
		y=to[i];
		if(y==fa[x]||y==son[x]) continue;
		dfs2(y,y);
	}
}

int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	return x;
}

void update(int x){
	if(vis[x]){
		if(--cnt[a[x]]==0) now--;
	}
	else if(++cnt[a[x]]==1) now++;
	vis[x]^=1;
}

int main()
{
	n=read(),m=read();blo=sqrt(2*n);
	for(int i=1;i<=n;i++) a[i]=read();
	int x,y;
	for(int i=1;i<=n;i++){
		x=read(),y=read();
		if(x&&y) add(x,y),add(y,x);
	}
	dfs1(1,0);dfs2(1,1);
	for(int i=1;i<=m;i++){
		x=read(),y=read(),q[i].a=read(),q[i].b=read();
		q[i].anc=LCA(x,y);q[i].id=i;
		if(x==q[i].anc||y==q[i].anc){
			q[i].anc=0;q[i].l=st[x];q[i].r=st[y];
			if(q[i].l>q[i].r) q[i].l=st[y],q[i].r=st[x];
		}
		else {
			q[i].l=ed[x];q[i].r=st[y];
			if(q[i].l>q[i].r) q[i].l=ed[y],q[i].r=st[x];
		}
	}
	sort(q+1,q+m+1,cmp);
	int L=1,R=0;
	for(int i=1;i<=m;i++){
		while(R<q[i].r) update(p[++R]);
		while(R>q[i].r) update(p[R--]);
		while(L<q[i].l) update(p[L++]);
		while(L>q[i].l) update(p[--L]);
		if(q[i].anc) update(q[i].anc);
		ans[q[i].id]=now;
		if(q[i].a!=q[i].b&&cnt[q[i].a]&&cnt[q[i].b]) ans[q[i].id]--;
		if(q[i].anc) update(q[i].anc);
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

3、Haruna’s Breakfast

小知识:带修莫队块大小在 \(n^{\frac 23}\) 跑的最快……不过我不会证

本人错误点:莫队修改过来的时候应该先将修改的时间戳 \(+1\),再更新;莫队修改回去的时候应该先更新,再将修改的时间戳 \(-1\)

\(Code\ Below:\)

#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn],pos[maxn],val[maxn],vis[maxn],cnt[maxn],ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,now,Cnum,Qnum,an;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];

struct Query{
    int l,r,anc,pre,id;
}q[maxn];

bool cmp(Query a,Query b){
    if((a.l-1)/blo!=(b.l-1)/blo)
        return (a.l-1)/blo<(b.l-1)/blo;
    if(a.r!=b.r) return a.r<b.r;
    return a.pre<b.pre;
}

inline int read(){
    register int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return (f==1)?x:-x;
}
inline void add(int x,int y){
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}

void dfs1(int x,int f){
    siz[x]=1;fa[x]=f;
    dep[x]=dep[f]+1;
    st[x]=++tim;p[tim]=x;
    int maxson=-1;
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];
        if(y==f) continue;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(maxson<siz[y]){
            maxson=siz[y];
            son[x]=y;
        }
    }
    ed[x]=++tim;p[tim]=x;
}

void dfs2(int x,int topf){
    top[x]=topf;
    if(son[x]) dfs2(son[x],topf);
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}

int LCA(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    return x;
}

inline void update(int x){
	if(a[x]<maxn){
		if(vis[x]){
	        if(--cnt[a[x]]==0) now=min(now,a[x]);
	    }
	    else if(++cnt[a[x]]==1) while(cnt[now]) now++;
	}
    vis[x]^=1;
}

inline void Del(int x){if(vis[x]&&a[x]<maxn) if(--cnt[a[x]]==0) now=min(now,a[x]);}
inline void Add(int x){if(vis[x]&&a[x]<maxn) if(++cnt[a[x]]==1) while(cnt[now]) now++;}

int main()
{
    n=read(),m=read();blo=pow(2*n,0.666666);
    for(int i=1;i<=n;i++) a[i]=read();
    int opt,x,y;
    for(int i=1;i<n;i++){
        x=read(),y=read();
        add(x,y);add(y,x);
    }
    dfs1(1,0);dfs2(1,1);
    for(int i=1;i<=m;i++){
        opt=read(),x=read(),y=read();
        if(opt==0){
        	pos[++Qnum]=x;val[Qnum]=y;
		}
		else {
			q[++Cnum].anc=LCA(x,y);q[Cnum].pre=Qnum;q[Cnum].id=Cnum;
			if(x==q[Cnum].anc||y==q[Cnum].anc){
	            q[Cnum].anc=0;q[Cnum].l=st[x];q[Cnum].r=st[y];
	            if(q[Cnum].l>q[Cnum].r) q[Cnum].l=st[y],q[Cnum].r=st[x];
	        }
	        else {
	            q[Cnum].l=ed[x];q[Cnum].r=st[y];
	            if(q[Cnum].l>q[Cnum].r) q[Cnum].l=ed[y],q[Cnum].r=st[x];
	        }
		}
    }
	sort(q+1,q+Cnum+1,cmp);
    int L=1,R=0;
    for(int i=1;i<=Cnum;i++){
        while(R<q[i].r) update(p[++R]);
        while(R>q[i].r) update(p[R--]);
        while(L<q[i].l) update(p[L++]);
        while(L>q[i].l) update(p[--L]);
        if(q[i].anc) update(q[i].anc);
        while(an<q[i].pre){
        	an++;
        	Del(pos[an]);
        	swap(a[pos[an]],val[an]);
        	Add(pos[an]);
		}
		while(an>q[i].pre){
			Del(pos[an]);
			swap(a[pos[an]],val[an]);
			Add(pos[an]);
			an--;
		}
		ans[q[i].id]=now;
        if(q[i].anc) update(q[i].anc);
    }
    for(int i=1;i<=Cnum;i++) printf("%d\n",ans[i]);
    return 0;
}

4、GT and trees

综合题,求树上路径待修改区间众数,不难想到带修树上莫队

然后就再记录一个 \(f[i]\) 表示区间出现 \(i\) 次的数的个数,\(add\) 没什么好说的,\(del\) 就暴力找,跟 \(mex\) 一样

\(Code\ Below:\)

#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],vis[maxn],f[maxn],cnt[maxn],pos[maxn],val[maxn];
int Ans[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,Cnum,Qnum,ans,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];

struct Query{
	int l,r,anc,pre,id;
}q[maxn];

bool cmp(Query a,Query b){
	if((a.l-1)/blo!=(b.l-1)/blo)
		return (a.l-1)/blo<(b.l-1)/blo;
	if(a.r!=b.r) return a.r<b.r;
	return a.pre<b.pre; 
}

inline int read(){
	register int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return (f==1)?x:-x;
}
inline void add(int x,int y){
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}

void dfs1(int x,int f){
	siz[x]=1;fa[x]=f;
	dep[x]=dep[f]+1;
	st[x]=++tim;p[tim]=x;
	int maxson=-1;
	for(int i=head[x],y;i;i=nxt[i]){
		y=to[i];
		if(y==f) continue;
		dfs1(y,x);
		siz[x]+=siz[y];
		if(maxson<siz[y]){
			maxson=siz[y];
			son[x]=y;
		}
	}
	ed[x]=++tim;p[tim]=x;
}

void dfs2(int x,int topf){
	top[x]=topf;
	if(son[x]) dfs2(son[x],topf);
	for(int i=head[x],y;i;i=nxt[i]){
		y=to[i];
		if(y==fa[x]||y==son[x]) continue;
		dfs2(y,y);
	}
}

int LCA(int x,int y){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	return x;
}

inline void update(int x){
	if(vis[x]){
		if(--f[cnt[a[x]]--]==0) while(!f[ans]) ans--;
	}
	else if(++f[++cnt[a[x]]]==1) ans=max(ans,cnt[a[x]]);
	vis[x]^=1;
}

inline void Add(int x){if(vis[x]) if(++f[++cnt[a[x]]]==1) ans=max(ans,cnt[a[x]]);}
inline void Del(int x){if(vis[x]) if(--f[cnt[a[x]]--]==0) while(!f[ans]) ans--;}

int main()
{
	int T=read();
	while(T--){
		memset(head,0,sizeof(head));
		memset(son,0,sizeof(son));
		memset(vis,0,sizeof(vis));
		memset(f,0,sizeof(f));
		memset(cnt,0,sizeof(cnt));
		tim=tot=Cnum=Qnum=ans=now=0;
		n=read(),m=read();blo=pow(2*n,0.666666);
		int opt,x,y;
		for(int i=1;i<n;i++){
			x=read(),y=read();
			add(x,y);add(y,x);
		}
		for(int i=1;i<=n;i++) a[i]=read();
		dfs1(1,0);dfs2(1,1);
		for(int i=1;i<=m;i++){
			opt=read(),x=read(),y=read();
			if(opt==0) pos[++Qnum]=x,val[Qnum]=y;
			else {
				q[++Cnum].anc=LCA(x,y);q[Cnum].pre=Qnum;q[Cnum].id=Cnum;
				if(x==q[Cnum].anc||y==q[Cnum].anc){
					q[Cnum].anc=0;
					if(st[x]<st[y]) q[Cnum].l=st[x],q[Cnum].r=st[y];
					else q[Cnum].l=st[y],q[Cnum].r=st[x];
				}
				else {
					if(ed[x]<st[y]) q[Cnum].l=ed[x],q[Cnum].r=st[y];
					else q[Cnum].l=ed[y],q[Cnum].r=st[x];
				}
			}
		}
		sort(q+1,q+Cnum+1,cmp);
		int L=1,R=0;
		for(int i=1;i<=Cnum;i++){
			while(R<q[i].r) update(p[++R]);
			while(R>q[i].r) update(p[R--]);
			while(L<q[i].l) update(p[L++]);
			while(L>q[i].l) update(p[--L]);
			if(q[i].anc) update(q[i].anc);
			while(now<q[i].pre){
				now++;
				Del(pos[now]);
				swap(a[pos[now]],val[now]);
				Add(pos[now]);
			}
			while(now>q[i].pre){
				Del(pos[now]);
				swap(a[pos[now]],val[now]);
				Add(pos[now]);
				now--;
			}
			Ans[q[i].id]=ans;
			if(q[i].anc) update(q[i].anc);
		}
		for(int i=1;i<=Cnum;i++) printf("%d\n",Ans[i]);
	}
	return 0;
}

5、[WC2013]糖果公园

树上带修莫队 我20分钟切掉的

其实差不多一个板子,不过我被卡常了,我 \(inline+register+O_2\) 才过,最大一个点 \(5136ms\)

// luogu-judger-enable-o2
#include <bits/stdc++.h>
#define res register int
#define ll long long
using namespace std;
const int maxn=100000+10;
int n,m,Q,c[maxn],v[maxn],w[maxn],vis[maxn],cnt[maxn],pos[maxn],val[maxn],st[maxn],ed[maxn],p[maxn<<1],tim,blo,Cnum,Qnum,now;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;ll Ans[maxn],ans;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];

struct Query{
    int l,r,anc,pre,id;
}q[maxn];

bool cmp(Query a,Query b){
    if((a.l-1)/blo!=(b.l-1)/blo)
        return (a.l-1)/blo<(b.l-1)/blo;
    if(a.r<b.r) return a.r<b.r;
    return a.pre<b.pre;
}

inline int read(){
    register int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return (f==1)?x:-x;
}
inline void add(res x,res y){
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}

void dfs1(res x,res f){
    siz[x]=1;fa[x]=f;
    dep[x]=dep[f]+1;
    st[x]=++tim;p[tim]=x;
    int maxson=-1;
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];
        if(y==f) continue;
        dfs1(y,x);
        siz[x]+=siz[y];
        if(maxson<siz[y]){
            maxson=siz[y];
            son[x]=y;
        }
    }
    ed[x]=++tim;p[tim]=x;
}

void dfs2(res x,res topf){
    top[x]=topf;
    if(son[x]) dfs2(son[x],topf);
    for(int i=head[x],y;i;i=nxt[i]){
        y=to[i];
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}

inline int LCA(res x,res y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y]) swap(x,y);
    return x;
}

inline void update(res x){
    if(vis[x]){
        ans-=(ll)v[c[x]]*w[cnt[c[x]]--];
    }
    else ans+=(ll)v[c[x]]*w[++cnt[c[x]]];
    vis[x]^=1;
}

inline void Del(res x){if(vis[x]) ans-=(ll)v[c[x]]*w[cnt[c[x]]--];}
inline void Add(res x){if(vis[x]) ans+=(ll)v[c[x]]*w[++cnt[c[x]]];}

int main()
{
    n=read(),m=read(),Q=read();blo=pow(2*n,0.666666);
    for(res i=1;i<=m;i++) v[i]=read();
    for(res i=1;i<=n;i++) w[i]=read();
    res opt,x,y;
    for(res i=1;i<n;i++){
        x=read(),y=read();
        add(x,y);add(y,x);
    }
    dfs1(1,0);dfs2(1,1);
    for(res i=1;i<=n;i++) c[i]=read();
    for(res i=1;i<=Q;i++){
        opt=read(),x=read(),y=read();
        if(opt==0) pos[++Qnum]=x,val[Qnum]=y;
        else {
            q[++Cnum].anc=LCA(x,y);q[Cnum].pre=Qnum;q[Cnum].id=Cnum;
            if(x==q[Cnum].anc||y==q[Cnum].anc){
                q[Cnum].anc=0;
                if(st[x]<st[y]) q[Cnum].l=st[x],q[Cnum].r=st[y];
                else q[Cnum].l=st[y],q[Cnum].r=st[x];
            }
            else {
                if(ed[x]<st[y]) q[Cnum].l=ed[x],q[Cnum].r=st[y];
                else q[Cnum].l=ed[y],q[Cnum].r=st[x];
            }
        }
    }
    sort(q+1,q+Cnum+1,cmp);
    res L=1,R=0;
    for(res i=1;i<=Cnum;i++){
        while(R<q[i].r) update(p[++R]);
        while(R>q[i].r) update(p[R--]);
        while(L<q[i].l) update(p[L++]);
        while(L>q[i].l) update(p[--L]);
        if(q[i].anc) update(q[i].anc);
        while(now<q[i].pre){
            now++;
            Del(pos[now]);
            swap(c[pos[now]],val[now]);
            Add(pos[now]);
        }
        while(now>q[i].pre){
            Del(pos[now]);
            swap(c[pos[now]],val[now]);
            Add(pos[now]);
            now--;
        }
        Ans[q[i].id]=ans;
        if(q[i].anc) update(q[i].anc);
    }
    for(res i=1;i<=Cnum;i++) printf("%lld\n",Ans[i]);
    return 0;
}
posted @ 2018-11-26 07:15  Owen_codeisking  阅读(269)  评论(0编辑  收藏  举报