ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「AHOI2022」钥匙

2022-06-08 08:34:27  阅读:150  来源: 互联网

标签:int AHOI2022 dep dfn 钥匙 mp siz 500005


想搞成一个好维护的形式,这个 \(5\) 把钥匙要用起来。

那首先考虑一点实现的问题,我们对同一种颜色建出虚树,然后以每个钥匙为根遍历一遍整棵树考虑造一点信息。

先看到 A 性质,猜测我们要通过一些特殊的匹配方式变成一条路径如果被包含则答案加一。

※ 那么考虑用栈储存钥匙,每次用栈顶解锁宝箱。然后栈底的钥匙(也就是当前的根)和与之匹配的宝箱形成一条合法路径(有方向)。

剩下的工作是个二维数点。虽然一眼看起来非常傻逼,但是思路比较巧妙阿。

/*
他决定要“格”院子里的竹子。于是他搬了一条凳子坐在院子里,面对着竹子硬想了七天,结果因为头痛而宣告失败。
DONT NEVER AROUND . //
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double DB;
typedef unsigned long long ULL;
char buf[1<<21],*p1=buf,*p2=buf;
#define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
int read()
{
	int x=0;
	char c=getchar();
	while(c<'0' || c>'9')	c=getchar();
	while(c>='0' && c<='9')	x=(x<<1)+(x<<3)+(c^'0'),c=getchar();
	return x;
}
void write(int x)
{
	if(x>9)	write(x/10);
	putchar(x%10+'0');
}
int fa[19][500005],siz[500005];
int lgs[500005],dep[500005];
int dfn[500005],sjc;
vector<int> G[500005];
vector<int> C[500005];
int n,q;
int t[500005],c[500005];
bool Ek[500005],Et[500005];
void dfs(int u,int f)
{
	dfn[u]=++sjc;
	dep[u]=dep[f]+1;
	fa[0][u]=f;
	siz[u]=1;
	for(auto v:G[u])	if(v^f)	dfs(v,u),siz[u]+=siz[v];
}
inline bool Inside(int u,int p){return dfn[u]<=dfn[p] && dfn[p]<dfn[u]+siz[u];}
inline int LCA(int u,int v)
{
	if(dep[u]>dep[v])	swap(u,v);
	while(dep[u]<dep[v])	v=fa[lgs[dep[v]-dep[u]]][v];
	if(u==v)	return u;
	for(int i=18;~i;--i)	if(fa[i][u]^fa[i][v])	u=fa[i][u],v=fa[i][v];
	return fa[0][u];
}
vector<int> V[500005];
int seq[1000005];
inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
void build(int col)
{
	static int cnt=0;
	for(int i=1;i<=cnt;++i)	V[seq[i]].clear();
	cnt=0;
	for(auto p:C[col])	seq[++cnt]=p;
	sort(seq+1,seq+1+cnt,cmp);
	for(int i=cnt;i>=2;--i)	seq[++cnt]=LCA(seq[i],seq[i-1]);
	sort(seq+1,seq+1+cnt,cmp);
	cnt=unique(seq+1,seq+1+cnt)-seq-1;
	for(int i=2,lca;i<=cnt;++i)	V[lca=LCA(seq[i-1],seq[i])].push_back(seq[i]),V[seq[i]].push_back(lca);
}
inline int lowbit(int x){return x&(-x);}
struct BinaryIndexedTree{
	int a[500005];
	void modify(int x,int v){for(int i=x;i<=n;i+=lowbit(i))	a[i]+=v;}
	void modify(int l,int r,int v){modify(l,v),modify(r+1,-v);}
	int query(int x){int ans=0;for(int i=x;i;i^=lowbit(i))	ans+=a[i];return ans;}
}bit;
vector<pair<pair<int,int>,int>> S[500005];
#define mp make_pair
inline int kthAcc(int u,int k){for(int i=18;~i;--i)	if((k>>i)&1)	u=fa[i][u];return u;}
inline void Add(int u,int v)
{
//	printf("%d %d\n",u,v);
	if(Inside(u,v))
	{
		int p=kthAcc(v,dep[v]-dep[u]-1);
		S[dfn[v]].push_back(mp(mp(1,dfn[p]-1),1));
		S[dfn[v]].push_back(mp(mp(dfn[p]+siz[p],n),1));
		S[dfn[v]+siz[v]].push_back(mp(mp(1,dfn[p]-1),-1));
		S[dfn[v]+siz[v]].push_back(mp(mp(dfn[p]+siz[p],n),-1));
	}
	else if(Inside(v,u))
	{
		int p=kthAcc(u,dep[u]-dep[v]-1);
		S[1].push_back(mp(mp(dfn[u],dfn[u]+siz[u]-1),1));
		S[dfn[p]].push_back(mp(mp(dfn[u],dfn[u]+siz[u]-1),-1));
		S[dfn[p]+siz[p]].push_back(mp(mp(dfn[u],dfn[u]+siz[u]-1),1));
	}
	else
	{
		S[dfn[v]].push_back(mp(mp(dfn[u],dfn[u]+siz[u]-1),1));
		S[dfn[v]+siz[v]].push_back(mp(mp(dfn[u],dfn[u]+siz[u]-1),-1));
	}
}
int F;
void Vdfs(int u,int f,int w=0)
{
	if(w<0)	return ;
//	printf("%d %d %d %d\n",F,u,f,w);
	for(auto v:V[u])
	{
		if(v==f)	continue;
		if(!w && c[v]==c[F] && t[v]==2)
		{
//			printf("%d: ",u),
			Add(F,v);
			continue;
		}
		int d=0;
		if(c[v]==c[F])
		{
			if(t[v]==1)	d=1;
			else	d=-1;
		}
		Vdfs(v,u,w+d);
	}
}
vector<pair<int,int>> Q[500005];
int ans[1000005];
int main(){
//	freopen("keys3.in","r",stdin);
//	freopen("keys.out","w",stdout);
	n=read(),q=read();
	for(int i=1;i<=n;++i)
	{
		t[i]=read(),c[i]=read();
		C[c[i]].push_back(i);
		if(t[i]==1)	Ek[c[i]]=true;
		else	Et[c[i]]=true;
	}
	for(int i=2;i<=n;++i)	lgs[i]=lgs[i>>1]+1;
	for(int i=1;i<n;++i)
	{
		int u=read(),v=read();
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1,0);
	for(int i=1;i<=18;++i)	for(int j=1;j<=n;++j)	fa[i][j]=fa[i-1][fa[i-1][j]];
	for(int i=1;i<=n;++i)
	{
		if(!Ek[i] || !Et[i])	continue;
		build(i);
		for(auto p:C[i])
		{
			if(t[p]==2)	continue;
			Vdfs(F=p,0);
		}
//		puts("");
	}
	for(int i=1;i<=q;++i)
	{
		int u=read(),v=read();
		Q[dfn[v]].push_back(mp(dfn[u],i));
	}
	for(int i=1;i<=n;++i)
	{
		for(auto st:S[i])	bit.modify(st.first.first,st.first.second,st.second);
		for(auto st:Q[i])	ans[st.second]=bit.query(st.first);
	}
	for(int i=1;i<=q;++i)	write(ans[i]),puts("");
	return 0;
}

标签:int,AHOI2022,dep,dfn,钥匙,mp,siz,500005
来源: https://www.cnblogs.com/amagaisite/p/16354214.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有