• 「AHOI2022」钥匙


    想搞成一个好维护的形式,这个 \(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;
    }
    
  • 相关阅读:
    Ionic在Generating ES5 bundles for differential loadind的时候报错
    将整个网站变为黑白 CSS3 filter grayscale
    ionic4 sqlite 的 executeSql 方法第二个参数不传会报错
    ionic4 执行ionic cordova run android 时报错Could not find plugin "proposal-numeric-separator". Ensure there is an entry in ./available-plugins.js for it.
    ion-picker组件示例(ionic4),这个组件有样式错乱的问题
    Linux下常用命令
    搜索引擎使用技巧
    Flex布局介绍
    0浏览器内幕探寻--源头
    Geolocation API
  • 原文地址:https://www.cnblogs.com/amagaisite/p/16354214.html
Copyright © 2020-2023  润新知