2018.10.29 bzoj4564: [Haoi2016]地图(仙人掌+莫队)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/83505970

传送门
根据原图建一棵新的树。
把原图每一个环上除了深度最浅的点以外的点全部向深度最浅的点连边。
然后可以搞出来一个 d f s dfs
这个时候我们就成功把问题转换成了对子树的询问。
然后就可以对权值分块用莫队做了注意如果不用分块而是用树状数组维护是O(nlognsqrt(n))的
代码:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
inline void write(int x){
	if(!x){putchar('0');return;}
	if(x>9)write(x/10);
	putchar((x-x/10*10)^48);
}
const int N=1e6+5,K=1e6+5;
int n,m,tot=0,dfn[N],low[N],a[N],col[N],siz[K],tim[K][2],in[N],Siz[N],pred[N],sig,ans[N],sig1,mx=0;
vector<int>e[N];
struct Query{int l,r,lim,f,id;}q[N];
inline int getp(int x,int z){return (x-1)/z+1;}
inline void tarjan(int p,int fa){
	dfn[p]=low[p]=++tot,pred[tot]=p;
	for(int i=0;i<e[p].size();++i){
		int v=e[p][i];
		if(v==fa)continue;
		if(!dfn[v])tarjan(v,p),low[p]=min(low[p],low[v]);
		else low[p]=min(low[p],dfn[v]);
	}
}
inline void dfs(int p,int fa){
	in[p]=++tot,Siz[p]=1;
	for(int i=0;i<e[p].size();++i){
		int v=e[p][i];
		if(v==fa)continue;
		if(!in[v]&&low[v]>=dfn[p])dfs(v,p),Siz[p]+=Siz[v];
	}
	for(int i=0;i<e[p].size();++i){
		int v=e[p][i];
		if(v==fa)continue;
		if(!in[v]&&low[v]<dfn[p])dfs(v,p),Siz[pred[low[v]]]+=Siz[v];
	}
}
inline void add(int pos){
	int upd=getp(pos,sig1);
	if(siz[pos]&1)--tim[upd][1],++tim[upd][0];
	else if(siz[pos])++tim[upd][1],--tim[upd][0];
	else ++tim[upd][1];
	++siz[pos];
}
inline void del(int pos){
	int upd=getp(pos,sig1);
	if(!(siz[pos]&1))++tim[upd][1],--tim[upd][0];
	else if(siz[pos]^1)--tim[upd][1],++tim[upd][0];
	else --tim[upd][1];
	--siz[pos];
}
inline bool cmp(const Query&a,const Query&b){return getp(a.l,sig)==getp(b.l,sig)?a.r<b.r:getp(a.l,sig)<getp(b.l,sig);}
int main(){
	n=read(),m=read(),sig=sqrt(n);
	for(int i=1;i<=n;++i)mx=max(mx,a[i]=read());
	sig1=sqrt(mx);
	for(int u,v,i=1;i<=m;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
	tarjan(1,0),tot=0,dfs(1,0),m=read();
	for(int i=1;i<=n;++i)col[in[i]]=a[i];
	for(int i=1,v;i<=m;++i)q[i].f=read(),v=read(),q[i].l=in[v],q[i].r=in[v]+Siz[v]-1,q[i].lim=read(),q[i].id=i;
	int ql=1,qr=0,sum=0;
	sort(q+1,q+m+1,cmp);
	for(int i=1;i<=m;++i){
		while(qr<q[i].r)add(col[++qr]);
		while(ql>q[i].l)add(col[--ql]);
		while(qr>q[i].r)del(col[qr--]);
		while(ql<q[i].l)del(col[ql++]);
		sum=0;
		int pos=getp(q[i].lim,sig1);
		for(int j=1;j<pos;++j)sum+=tim[j][q[i].f];
		int L=(pos-1)*sig1+1,R=q[i].lim;
		for(int j=L;j<=R;++j){
			if(!siz[j])continue;
			sum+=(siz[j]&1)==q[i].f;
		}
		ans[q[i].id]=sum;
	}
	for(int i=1;i<=m;++i)write(ans[i]),puts("");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/83505970
今日推荐